Friday, April 13, 2012

Singleton value converters in WPF

I saw this interesting post about using singleton value converters by Amit:
WPF Binding Converter Best Practices
The discussions there sort of concluded that WPF creates a single instance of converters anyway, so implementing singletons does not add much value.
I guess it is true that for a given "window", the converters are created only once per definition in the Resources.
But, if I have many windows, each with their own resource definitions of these converters, then these converters are atleast created once for each window. If I have 50 converters, and users keep creating and closing windows, then those 50 converters would get created every time a window gets created.
To avoid this, it would make sense to implement converters as singletons as suggested by Amit. With that, my subsequent windows should load faster because they don't need to construct all the converters again.
I am implementing performance improvements in my app and I think this is a small bit that will add up :)

Wednesday, October 19, 2011

Refactoring to expose an ObservableCollection as a ReadOnlyObservableCollection property

I was working with ObservableCollection<> objects and as the code/design/architecture matured, I wanted to expose them as true read-only properties.
This is what my initial code looked like:

//This is what I had
private ObservableCollection<int> _myIntCollection;
publ ObservableCollection<int> myIntCollection
{
//This does not give me much other than not being able to create a new myIntCollection. I can add/delete items from the collection
    get
    {
        return _myIntCollection;
    }
}
//...Code that creates a new _myIntCollection who knows where and how many times

Intellisense showed me ReadOnlyObservableCollection<> along with ObservableCollection<> and that looked like just what I wanted!

//First change
private ObservableCollection<int> _myIntCollection;
public ReadOnlyObservableCollection<int> myIntCollection
{
    get
    {
//Cool: now my presenters/clients cannot modify the collection also
//But: I create a new collection on every read,
//and that can affect the performance as well as cause other unexpected issues
        return new ReadOnlyObservableCollection<int>(_myIntCollection);
    }
}
//...Code that creates a new _myIntCollection who knows where and how many times

I figured that it is not neat to create a new instance of a readonly collection every time I want to access the property, and found this post:
ReadOnlyObservableCollection anti-pattern
I liked the idea of creating the new readonly collection when I create my base observable collection, but I did not want find all references and add code to every "new" statement.
A more manageable way of refactoring to expose an ObservableCollection as a ReadOnlyObservableCollection is to convert the base ObservableCollection object also into a property that initializes the ReadOnlyObservableCollection object whenever the base object is set:

//Much better, and I don't have to worry about
//"who knows where and how many times" _myIntCollection is created in my code

//The real writable collection
private ObservableCollection<int> _w_myIntCollection;

//My existing code uses _myIntCollection to create the collection and I don't want to change that
private ObservableCollection<int> _myIntCollection
{
    get
    {
        return _w_myIntCollection;
    }
    set
    {
        _w_myIntCollection = value;
//with this, whereever there is _myIntCollection = new ObservableCollection in the existing code,
//it will create my readonly collection also now
        _r_myIntCollection = new ReadOnlyObservableCollection<int>(_w_myIntCollection);
    }
}
//my read-only collection used within the class
private ReadOnlyObservableCollection<int> _r_myIntCollection;

//read-only property so that presenters/clients cannot create a new read-only collection
public ReadOnlyObservableCollection<int> myIntCollection
{
    get
    {
        return _r_myIntCollection;
    }
}
//...Code that creates a new _myIntCollection who knows where and how many times

Friday, October 14, 2011

Multidimensional Indexed property binding in WPF

When I searched for indexed property binding in WPF, I did find some useful information like this one:
If I have a binding like so in XAML:
Text="{Binding [5], Mode=OneWay}"

Then, with this, if my datacontext has an integer indexer this[int indx] then I would get the element at index 5.
And if my datacontext has an indexer this[string sindx] (and no integer indexer), then I will get the element indexed by "5".
So far so good.

But, if I want to bind to a multidimensional indexed property, then it took a bit of "research" to figure out that I can do it by:
Text="{Binding [5\,1], Mode=OneWay}"

Good to know... {Binding [2\,hello], Mode=OneWay} in the example below translates to:


            Binding b = new Binding("[2,hello]");
            b.Mode = BindingMode.OneWay;
            textBlock5.SetBinding(TextBox.TextProperty, b);

XAML to test indexer binding:



<TextBox Name="textBlock1" Text="{Binding [5], Mode=OneWay}" />
<TextBox Name="textBlock2" Text="{Binding [some\,string],Mode=OneWay}" />
<TextBox Name="textBlock3" Text="{Binding (Name), Mode=OneWay,RelativeSource={x:Static RelativeSource.Self }}" />
<TextBox Name="textBlock4" Text="{Binding SomeProp, Mode=OneWay}" />
<TextBox Name="textBlock5" Text="{Binding [2\,hello], Mode=OneWay}" />
<TextBox Name="textBlock6" Text="{Binding [Jagged][Jagged indexer property], Mode=OneWay}"/>


ViewModel:

    public class TestVM : INotifyPropertyChanged
    {
        public string this[int i]
        { get { return "Int single dimensional indexer: " + i.ToString(); } }
        public string this[string s1, string s2]
        { get{ return "String Multi Dimensional Indexer Called: " + s1 + " , " + s2; } }
        public string this[int i1, string s1]
        { get{ return "Integer String Multi Dimensional Indexer Called: " + i1.ToString() + " , " + s1; } }
        public string SomeProp
        { get{ return "SomeProp: Hello";} }
        public object this[string s]
        {
            get
            {
                if (s == "Jagged")
                    return this;//Just being lazy: test accessing something as [][] when the initial indexer is "Jagged"
                else
                    return "String single dimensional indexer: " + s;
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void Notify(string propertyname)
        {if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyname)); }
    }