Getting All Static Fields In a Class Hierarchy

Using reflection is pretty straight forward and that's why I found it weird that I was trying to get all the Dependency Properties for the Silverlight ComboBox but I was only getting the fields defined in the class itself. None of the fields found in the base classes where being retrieved. Only then I learned something new about reflection and static fields. Here is the code I expected to work but doesn't.
FieldInfo[] fields =
     typeof (ComboBox).GetFields(BindingFlags.Static | BindingFlags.Public);
When reflecting over a class to get all it's static fields you will find out that static fields from base classes are really not retrieved by default. And since all Dependency Properties are static fields you can't get the DP's from the base classes. If you want to retrieve all the static fields in a class hierarchy you need a special BindingFlag: BindingFlags.FlattenHierarchy. This will bring all your static fields including the one from the base classes.
 FieldInfo[] fields =
     typeof (ComboBox).GetFields(BindingFlags.Static | BindingFlags.Public |
                                 BindingFlags.FlattenHierarchy);

 Hope this is a useful tip.

MVVM ProgressBar

There are a lot of options for doing a ProgressBar in WPF using MVVM you can Google it and see for yourself. In this article I'll show a hybrid way of doing MVVM and having a ProgressBar that does not conform to the MVVM premiss (but it is really simple to use).

 The idea is that you can do all the things you are used to do with MVVM but when you get to the ProgressBar you use events and a little code-behind.

Here is the code for the ViewModel:

public class MainWindowViewModel
{
    private BackgroundWorker _backgroundWorker;

    public event EventHandler TaskStarting = (s,e) => { };

    public event ProgressChangedEventHandler ProgressChanged
    {
        add { _backgroundWorker.ProgressChanged += value; }
        remove { _backgroundWorker.ProgressChanged -= value; }
    }

    public event RunWorkerCompletedEventHandler TaskCompleted
    {
        add { _backgroundWorker.RunWorkerCompleted += value; }
        remove { _backgroundWorker.RunWorkerCompleted -= value; }
    }

    private ICommand _executeLongTask;

    public ICommand ExecuteLongTask
    {
        get
        {
            if (_executeLongTask == null)
            {
                _executeLongTask = new RelayCommand(param => _backgroundWorker.RunWorkerAsync());
            }
            return _executeLongTask;
        }
    }

    public MainWindowViewModel()
    {
        _backgroundWorker = new BackgroundWorker();
        _backgroundWorker.WorkerReportsProgress = true;
        _backgroundWorker.DoWork += executeTask;
    }

    private void executeTask(object sender, DoWorkEventArgs e)
    {
        OnTaskStarting();
        for (int i = 0; i < 100; i++)
        {
            Thread.Sleep(100);
            _backgroundWorker.ReportProgress(i + 1);
        }
    }

    private void OnTaskStarting()
    {
        TaskStarting(this, EventArgs.Empty);
    }
}

 This ViewModel class has three events: TaskStartiing, ProgressChanged and TaskCompleted. The last two are just events that I exposed from the BackgroundWorker that will execute my long runing task. The code-behind for the Window will subscribe to these events:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        MainWindowViewModel vm = new MainWindowViewModel();
        vm.TaskStarting += TaskStarted;
        vm.ProgressChanged += ProgressChanged;
        vm.TaskCompleted += TaskCompleted;

        DataContext = vm;
    }

    void TaskStarted(object sender, EventArgs e)
    {
        this.Dispatcher.Invoke(new Action(() => ProgressPopup.IsOpen = true));
    }

    void TaskCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
    {
        this.Dispatcher.Invoke(new Action(() => ProgressPopup.IsOpen = false));
    }

    void ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
    {
        this.Dispatcher.Invoke(new Action(() => ProgressBar.Value = e.ProgressPercentage));
    }
}

Notice that since my long running task is being executed in another thread I need to use the Dispatcher to update any user interface elements.

My Window has a Popup with a ProgressBar inside it. I use the Starting and Completed events to show and hide the Popup. The ProgressBar itself is only updated in the ProgessChanged event. I also added an animation to show a blinking progress message during the execution.

<Window x:Class="MvvmProgressBar.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="300" Width="400">
    <StackPanel>
        <Button Command="{Binding ExecuteLongTask}">Run Long Task</Button>
        <Popup Name="ProgressPopup" 
               Placement="Center" 
               Width="300"
               IsOpen="False">
            <Border BorderThickness="10"
                    BorderBrush="Black"
                    Background="Gray"
                    Padding="30,50">
                <StackPanel>
                    <TextBlock Foreground="White"
                           FontWeight="Bold"
                           FontSize="16"
                           Name="txt"
                           Text="Processing...">
                    <TextBlock.Triggers>
                        <EventTrigger RoutedEvent="TextBlock.Loaded">
               <BeginStoryboard>
                  <Storyboard>
                     <DoubleAnimation
                        AutoReverse="True"
                        Duration="0:0:1"
                        From="1.0"
                        RepeatBehavior="Forever"
                        Storyboard.TargetName="txt"
                        Storyboard.TargetProperty="Opacity"
                        To="0.0"/>
                  </Storyboard>
               </BeginStoryboard>
            </EventTrigger>
                    </TextBlock.Triggers>
                    </TextBlock>
                    <ProgressBar Name="ProgressBar"
                                 Height="30" 
                                 BorderThickness="2" />
                </StackPanel>
            </Border>
        </Popup>
    </StackPanel>
</Window>

This example is really simple but it goes to show you that you may, from time to time, do some non-MVVM code and it won't make your app suck.

 

MVVM Multiselect Listbox

Although MVVM is a great pattern you have to learn to work with it somethings are hard to do until you get the hang of it.

One of these things is doing a Multiselect Listbox. My first idea Google it, of course. The best solution I found was this one by Marlon Grech. Marlon has a lot of good stuff about WPF in his blog and he definitely knows what he is talking about. This solution however became a little slow when I wanted to perform a Select All and Unselect All on the list.

I decided to implement a specialized list for this kind of situation. I call it a SelectionList and it is a list of SelectionItems. The idea is to have a collection of items that have a IsSelected property and a Item property that contains the real value you want. I think the code speaks for itself.

public class SelectionItem<T> : INotifyPropertyChanged
{
    #region Fields

        private bool isSelected;

        private T item;

        #endregion

    #region Properties

        public bool IsSelected
        {
            get { return isSelected; }
            set
            {
                if (value == isSelected) return;
                isSelected = value;
                OnPropertyChanged("IsSelected");
                OnSelectionChanged();
            }
        }

        public T Item
        {
            get { return item; }
            set
            {
                if (value.Equals(item)) return;
                item = value;
                OnPropertyChanged("Item");
            }
        }

        #endregion

    #region Events

        public event PropertyChangedEventHandler PropertyChanged;

        public event EventHandler SelectionChanged;

        #endregion

    #region ctor

        public SelectionItem(T item)
            : this(false, item)
        {
        }

        public SelectionItem(bool selected, T item)
        {
            this.isSelected = selected;
            this.item = item;
        }

        #endregion

    #region Event invokers

        private void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler changed = PropertyChanged;
            if (changed != null) changed(this, new PropertyChangedEventArgs(propertyName));
        }

        private void OnSelectionChanged()
        {
            EventHandler changed = SelectionChanged;
            if (changed != null) changed(this, EventArgs.Empty);
        }

        #endregion
}

 The SelectionItem class is what really makes things happen. It takes an ordinary class like an string and wraps it adding a IsSelected property. This is the class of the objects that will be bound to each ListItem of the ListBox.

public class SelectionList<T> : 
    ObservableCollection<SelectionItem<T>> where T : IComparable<T>
{
    #region Properties

        /// <summary>
        /// Returns the selected items in the list
        /// </summary>
        public IEnumerable<T> SelectedItems
        {
            get { return this.Where(x => x.IsSelected).Select(x => x.Item); }
        }

        /// <summary>
        /// Returns all the items in the SelectionList
        /// </summary>
        public IEnumerable<T> AllItems
        {
            get { return this.Select(x => x.Item); }
        }

        #endregion

    #region ctor

        public SelectionList(IEnumerable<T> col)
            : base(toSelectionItemEnumerable(col))
        {

        }

        #endregion

    #region Public methods

        /// <summary>
        /// Adds the item to the list
        /// </summary>
        /// <param name="item"></param>
        public void Add(T item)
        {
            int i = 0;
            foreach (T existingItem in AllItems)
            {
                if (item.CompareTo(existingItem) < 0) break;
                i++;
            }
            Insert(i, new SelectionItem<T>(item));
        }

        /// <summary>
        /// Checks if the item exists in the list
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Contains(T item)
        {
            return AllItems.Contains(item);
        }

        /// <summary>
        /// Selects all the items in the list
        /// </summary>
        public void SelectAll()
        {
            foreach (SelectionItem<T> selectionItem in this)
            {
                selectionItem.IsSelected = true;
            }
        }

        /// <summary>
        /// Unselects all the items in the list
        /// </summary>
        public void UnselectAll()
        {
            foreach (SelectionItem<T> selectionItem in this)
            {
                selectionItem.IsSelected = false;
            }
        }

        #endregion

    #region Helper methods

        /// <summary>
        /// Creates an SelectionList from any IEnumerable
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        private static IEnumerable<SelectionItem<T>> toSelectionItemEnumerable(IEnumerable<T> items)
        {
            List<SelectionItem<T>> list = new List<SelectionItem<T>>();
            foreach (T item in items)
            {
                SelectionItem<T> selectionItem = new SelectionItem<T>(item);
                list.Add(selectionItem);
            }
            return list;
        }

        #endregion
}

The SelectionList is basically an ObservableCollection of SelectionItem.

Now that you have a list of items that can be bound to each ListBoxItem I needed to figure out how to bind the IsSelected property of my items to the is IsSelected property of the ListBoxItem. I found the solution in

this post

in the MSDN Forums. You need to use this style:

<ListBox.ItemContainerStyle>
    <Style TargetType="{x:Type ListBoxItem}">
        <Setter Property="IsSelected" 
                Value="{Binding IsSelected}"/>
    </Style>
</ListBox.ItemContainerStyle>

Example:

Imagine you need a window with a list of sports from which you have to select the sports you like. In this window you need to be able to add items to the list and select and unselect all items at once. Here is the code for the window and the ViewModel:

<Window x:Class="MvvmChecklistBox.MultiSelectWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MvvmChecklistBox"
        Title="MultiSelectWindow" Height="300" Width="300">
    <Window.Resources>
        <local:MainWindowViewModel x:Key="viewModel"/>
    </Window.Resources>
    <StackPanel Margin="5" DataContext="{StaticResource viewModel}">
        <TextBlock>Sport:</TextBlock>
        <TextBox Name="textBoxNewSport"
                 Text="{Binding NewSport}"/>
        <Button Content="Add new sport"
                Command="{Binding AddCommand}"/>
        <ListBox Name="checkboxList"
                 ItemsSource="{Binding Sports}"
                 DisplayMemberPath="Item"
                 Margin="0,5" 
                 SelectionMode="Multiple">
            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Setter Property="IsSelected" 
                            Value="{Binding IsSelected}"/>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
        <Button Content="Select All"
                Margin="0,5"
                Command="{Binding SelectAllCommand}"/>
        <Button Content="Unselect All"
                Margin="0,5"
                Command="{Binding UnselectAllCommand}"/>
    </StackPanel>
</Window>
public class MainWindowViewModel : INotifyPropertyChanged
{
    #region Fields

        private ICommand _selectAllCommand;

        private ICommand _unselectAllCommand;

        private ICommand _addCommand;

        private string _newSport;

        #endregion

    #region Properties

        public SelectionList<string> Sports { get; set; }

        public string NewSport
        {
            get { return _newSport; }
            set
            {
                if (value == _newSport) return;
                _newSport = value;
                OnPropertyChanged("NewSport");
            }
        }

        #endregion

    #region Commands

        public ICommand SelectAllCommand
        {
            get
            {
                if (_selectAllCommand == null)
                {
                    _selectAllCommand = new RelayCommand(param => Sports.SelectAll());
                }
                return _selectAllCommand;
            }
        }

        public ICommand UnselectAllCommand
        {
            get
            {
                if (_unselectAllCommand == null)
                {
                    _unselectAllCommand = new RelayCommand(param => Sports.UnselectAll());
                }
                return _unselectAllCommand;
            }
        }

        public ICommand AddCommand
        {
            get
            {
                if (_addCommand == null)
                {
                    _addCommand = new RelayCommand(param =>
                    {
                        Sports.Add(NewSport);
                        NewSport = string.Empty;
                    });
                }
                return _addCommand;
            }
        }

        #endregion

    #region Events

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

    #region ctor

        public MainWindowViewModel()
        {
            string[] sports = { "Baseball", "Basketball", "Football", "Handball", "Soccer", "Volleyball" };
            Sports = new SelectionList<string>(sports);
        }

        #endregion

    #region Event invokers

        private void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler changed = PropertyChanged;
            if (changed != null) changed(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion
}

Here is the result:

MultiSelectWindow

The solution was really simple after I though of the SelectionList. I wanted however to do a little bit more. Instead of the simple Listbox I had to build a list of CheckBoxes. To good thing is that as far as the ViewModel is concerned we are all set, there's no need to change anything. All we need to change is the View (which is a Window in our case) using a DataTemple in the ListBox ItemTemplate to place a Checkbox instead of regular item.

<ListBox.ItemTemplate>
    <DataTemplate>
        <CheckBox IsChecked="{Binding IsSelected}" 
                  Content="{Binding Item}"/>
    </DataTemplate>
</ListBox.ItemTemplate>

Did it work? Kind of... It works but something weird happens because you can select all the checkboxes you want and then select the ListItem which gets highlighted. So now you have the checkbox selection and the item highlight selection and the two of them do not match. I don't want the ListBox item to get highlighted. Once again Google helped and I found a style to do just what I wanted in Alex Filo's blog. Here is the code:

<ListBox.ItemContainerStyle>
    <Style>
        <Setter Property="ListBoxItem.Background" Value="Transparent"/>
        <Setter Property="ListBoxItem.Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <Border x:Name="Bd" 
                    SnapsToDevicePixels="true" 
                    Background="{TemplateBinding Background}" 
                    BorderBrush="{TemplateBinding BorderBrush}" 
                    BorderThickness="{TemplateBinding BorderThickness}" 
                    Padding="{TemplateBinding Padding}">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter Property="Background" TargetName="Bd" Value="Transparent" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ListBox.ItemContainerStyle>

CheckBoxListError

Now we're done! Here is the final code for the view:

<Window x:Class="MvvmChecklistBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="300">
    <StackPanel Margin="5">
        <TextBlock>Sport:</TextBlock>
        <TextBox Name="textBoxNewSport"
                 Text="{Binding NewSport}"/>
        <Button Content="Add new sport"
                Command="{Binding AddCommand}"/>
        <ListBox Name="checkboxList"
                 ItemsSource="{Binding Sports}"
                 Margin="0,5">
            <ListBox.ItemContainerStyle>
                <Style>
                    <Setter Property="ListBoxItem.Background" Value="Transparent"/>
                    <Setter Property="ListBoxItem.Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                <Border x:Name="Bd" 
                                SnapsToDevicePixels="true" 
                                Background="{TemplateBinding Background}" 
                                BorderBrush="{TemplateBinding BorderBrush}" 
                                BorderThickness="{TemplateBinding BorderThickness}" 
                                Padding="{TemplateBinding Padding}">
                                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="true">
                                        <Setter Property="Background" TargetName="Bd" Value="Transparent" />
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.ItemContainerStyle>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <CheckBox IsChecked="{Binding IsSelected}" 
                              Content="{Binding Item}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button Content="Select All"
                Margin="0,5"
                Command="{Binding SelectAllCommand}"/>
        <Button Content="Unselect All"
                Margin="0,5"
                Command="{Binding UnselectAllCommand}"/>
    </StackPanel>
</Window>

I'm sure that someone has had this problem and the SelectionList seems like a straight forward solution. I haven't found anything like it but I'm sure I can't be the first to think of it. Well, I hope this helps you and if you find of think of a better solution please leave a comment.

Dependency Properties

Dependency Properties are quite different from regular CLR properties. Let's take an Age property as a simple example of a normal property. We usually define a private field of type int and then define a Age property wrapping this field with get and set accessors. The code should be something like this:

public class Person
{
    private int _age;
    public int Age
    {
        get { return _age; }
        set { _age = value; }
    }
}

If instead we wanted to create age as a dependency property instead the code would look like this:

public class Person : DependencyObject
{
    public static readonly DependencyProperty AgeProperty = DependencyProperty.Register("Age", typeof (int),
                                                                                        typeof (Person));
    public int Age
    {
        get { return (int)GetValue(Person.AgeProperty); }
        set { SetValue(Person.AgeProperty, value); }
    }
}

 

Wow, that is really different isn't it? Actually it is so different that I rather take it apart so that we can understand each piece of this code.

Part 1: The class

Dependency properties can only be used in classes that derive from DependencyObject. As you can see in the first example the Person class is a simple class derived from the Object class. In the second example Person is derived from DependencyObject.

DependencyObject is the class that has all the necessary infrastructure that make DP's work. As we go through this article I'll mention more about this class but for now just keep in mind that if you want or need to use DP's your class must derive from DependencyObject.

Part 2: Declaring the Property

As you may have noticed the two examples are totally different. By convention the DP is a public static readonly field of the type DependencyProperty. So the field that will store the actual value of age is not an int? Yep, that is it. As you can see the field if of type DependecyProperty. This is all part of the DP way of life. The actual type of the age (which we know is int) will only be know when instantiating the DP.

Another thing that you may be wondering about is that the filed was named AgeProperty instead of just Age. The suffix Property is included as a convention to denote that this is the static field to the DP.

Part 3: Instantiation

The DependencyProperty class doesn't have a public constructor. To create an instance of this class we need to use the use the Register static method.

 

The simpler overload of this method takes three parameters, the first is a string that sets the name of the DP (Age in our case), the second expects the type of the property, which is int, and the last one represents the type of the class to which the DP is associated (in our example is the class Person).

 

The creation of the DP may be done inline as we've done in our example or it may be move in the static constructor like this:

public static readonly DependencyProperty AgeProperty;
static Person()
{
    AgeProperty = DependencyProperty.Register("Age", typeof(int), typeof(Person));
}

This code is more than a Factory to instantiate the DependencyProperty object, it also (as the name very well describes) registers the new property within the DP infrastructure. If you are interested in low level details, the actual registration occurs a private method called RegisterCommon of the DependencyProperty class. Download the framework source code or use Reflector to look inside.

Part 4: Wrapping the DP

Now that you saw what is really behind a DP you may be asking yourself. Ok, so my property is age of type int, but the DP is actually of type DependencyProperty, so how do I assign a value of 30 to the object that is not really an int? Cool, you are on the right track then!
The work of getting and setting the values of DPs goes through the DependencyObject class. It has a SetValue method for setting the value of the property and a GetValue method to retrieve the value. These methods are public you may use them directly like in the example below:

Person person = new Person();
person.SetValue(Person.AgeProperty, 31);
int myAge = (int)person.GetValue(Person.AgeProperty);

Since these methods are part of the DependencyObject class is clear that they are general purpose methods to retrieve or set values of properties. It is pretty straight forward then that you have to tell which property you want to get the value from. That is when you use your static DependencyProperty field that was already registered. Also the GetValue returns an instance of the class Object so you need to cast it to your type.
This is all good but I bet you are saying that this syntax is too verbose, right? Don't worry I think so too and the WPF team as well. In order to provide easy access to the DPs you may use property wrappers, like in our example. Using this strategy you code will become easier to work with and people don't even have to know if the property is a DP or not.

Person person = new Person();
person.Age = 31;
int myAge = person.Age;

IMPORTANT
When using properties you should be advised that you should not use any other code within the get or set accessors. This warning is documented in every book or piece of documentation I've read so far! Doing anything but using GetValue or SetValue in the accessors may really mess up your program. The thing is that WPF will use in many parts of it's code the GetValue and SetValue methods instead of your property wrapper. If your wrapper adds any thing to the mix you may have inconsistent results through your application, so watch out for this.

But wait, there's more

Now that we have the base idea of DP, let's keep going and try to understand few more concepts.

LocalValue vs EffectiveValue

Understanding this distinction really important in the process of learning WPF. The actual distinction is not even visible at first, but as soon as you begin to study coercion you notice that there is something more than just a value to the property.
The LocalValue is the "real" value, or the value that you set to the property. This value is stored but it may not be the one displayed if you try to use the GetValue method. But why would the property show a value other than the one you set? Let's imagine that in our example we could have a MinAge and a MaxAge properties and we set the values as in the following code:

person.MinAge = 21;
person.MaxAge = 150;
person.Age = 15;
int age = person.Age;

Setting the Age to 15 would not be allowed since the minimum value is 21. The DP infrastructure code has was to enforce these constraints (I'll show it a bit latter). When the code reads the property reads the Age it will return 21 which is the EffectiveValue. Does this implies that the 15 is gone? Nope! The 15 is still stored as the LocalValue (or real value if you will), if you don't believe me just use the ReadLocalValue method to read the Age property.
So the EffectiveValue is the result of applying constraints (or corrections) over the LocalValue. More often than not these values will actually be different.
One last thing about Local vs Effective is how the default value of the property is set. Age is an int, right? What is the default value for an int? Yep, 0 (zero) is the correct answer! So if you do person.Age you expect it to return 0 if you have not done any other initialization to this property. By now you probably figured out that the EffectiveValue has to be initialized to the default value of the property type. So EffectiveValue stores 0. The LocalValue on the other hand only gets a value when it set explicitly. But what is it's value mean while? Null? No, when the LocalValue is not set, the ReadLocalValue will return DependencyProperty.UnsetValue which is a public static field on the DependecyProperty class.

FrameworkPropertyMetadata

This class provides way to pass more parameters for the DependencyProperty. So far our property works fine, but we could do a little more with the FrameworkPropertyMetadata. Let's see some of the important properties that you can pass to the DP through the metadata:

  • DefaultValue: Using this property you can set the default value for the DP
  • CoerceValueCallback: This callback will try to make adjustments (or correct) to the value of the property. Coercion is a concept that we'll discuss a little latter.
  • PropertyChangedCallback: This callback will be fired when the value of the property is changed.
DefaultValue

Let's you pass in a default value for the DP. When you create an instance of the class Person the Age will be equals to 0 (zero). Now a challenge: When the DefaultValue is set where is this value stored, in the LocalValue or EffectiveValue? If you said EffectiveValue you are right. Try to use the ReadLocalValue and you'll see that the value is defined as DependecyProperty.UnsetValue.

Person person = new Person();
object o1 = person.Age; //returns 0
object o2 = person.GetValue(Person.AgeProperty); //is the same thing as the line above
object o3 = person.ReadLocalValue(Person.AgeProperty); // returns DependencyProperty.UnsetValue
CoerceValueCallback

This callback is set to a method that is going to take the value that is attributed to the property and apply some kind of correction to it. Setting a value to the property will change the value of the LocalValue and the EffectiveValue but if the CoerceValueCallback makes some change to the value this modified value is stored in the EffectiveValue while the original, unchanged attributed value is stored in the LocalValue. Let's say that any Age greater than 100 needs to be set as 100. The method to this is really simple:

 

private static object CoerceAgeValue(DependencyObject d, object baseValue)
{
    int age = (int)baseValue;
    return Math.Min(100, age);
} 

Now let's see how an instance of the class Person would behave when having it's value set:

Person person = new Person();
person.Age = 105; //will cause the value to be coerced
object o2 = person.GetValue(Person.AgeProperty); //returns 100 (this is the coerced value)
object o3 = person.ReadLocalValue(Person.AgeProperty); //returns 105 (this is the original value)

Another great example of the power given by this resource is the use of a ScrollBar:

ScrollBar bar = new ScrollBar();
//value = 0 (LV=Unset, EV=0), min = 0, max = 1


The ScrollBar has just been created and it's values are still the default values. Now let's change the Value to 100.

bar.Value = 100;
//value = 1 (LV=100, EV=1), min = 0, max = 1


The LocalValue is now 100 but the EffectiveValue was coerced to respect the Min and Max values. Though the Value shows 1 the actual value is still stored and was not lost.

bar.Minimum = 1;
//value = 1 (LV=100, EV=1), min = 1, max = 1


The Min value is set but it doesn't change the outcome for us.

bar.Maximum = 200;
//value = 100 (LV=100, EV=100), min = 1, max = 200


Now that the Max was set to 200 the coercion will not need to change the value stored in the Value property. Now it finally shows as 100 as we had originally defined. This means that the order in which you set the properties will not affect the final result. If it was not for the was DPs work you would need to first define the Min and Max and only then you could the set Value. This is awesome!!

PropertyChangedCallback

This has one simple mission: Notify that a change was made to the property. In the ScrollBar whenever the Minimum or Maximum are changed a callback is fired, this callback is responsible for coercing the Value of the control using the new Maximum or Minimum.

ValidateValueCallback

The ValidateValueCallback is the last parameter of the DepenencyProperty.Register method. This callback points to a method that will validate the value being attributed to the property. Here is an example of a validation of the Age property:

private static bool ValidateAgePropertyValue(object value)
{
    int age = (int)value;
    return age >= 0;
}

In this method we validate that the Age is greater than zero after all there is no negative ages. I know that you are thinking that this is very similar to the coercion concept, right? They way I perceive the difference is that the Validation is trying to identify an incorrect value while the the Coercion takes a valid value and makes some adjustments according to other properties in the object like the Minimum or Maximum in the ScrollBar example.

Another difference between the two is that the Validate method has one single parameter which is the new value that is being set. Since the method is a static method you do not have access to any other properties in the object which imposes a limitation on the kind of validation that could be made. The Coercion callback has two parameters: the dependency object that has the value and the new value for the property. Since this callback has access to the dependency object it is the ideal place to make the kind of tests that will try to limit the value between a minimum and a maximum.

Putting it all together

I know this is a lot to digest so the best way to really understand it all is to see a full example.

The following code is for a Car class with 3 Dependency Properties: Speed, MaxSpeed and MinSpeed. The speed has to be between the minimum and maximum. Every time the one of these properties is changed the others must me adjusted in order to keep the constraints we imposed.

public class Car : DependencyObject
    {
        #region Dependency Properties

        public static readonly DependencyProperty SpeedProperty;

        public static readonly DependencyProperty MinSpeedProperty;

        public static readonly DependencyProperty MaxSpeedProperty;

        #endregion


        #region Dependency Properties Wrappers

        /// <summary>
        /// Wrapper for the Speed dependency property
        /// </summary>
        public int Speed
        {
            get { return (int)GetValue(SpeedProperty); }
            set { SetValue(SpeedProperty, value); }
        }

        /// <summary>
        /// Wrapper for the MinSpeed dependency property
        /// </summary>
        public int MinSpeed
        {
            get { return (int)GetValue(MinSpeedProperty); }
            set { SetValue(MinSpeedProperty, value); }
        }

        /// <summary>
        /// Wrapper for the MaxSpeed dependency property
        /// </summary>
        public int MaxSpeed
        {
            get { return (int)GetValue(MaxSpeedProperty); }
            set { SetValue(MaxSpeedProperty, value); }
        }

        #endregion

        /// <summary>
        /// Static constructor where all dependecy properties are being initialized
        /// </summary>
        static Car()
        {
            Trace.WriteLine("Static Constructor");
            //configure and register speed property
            FrameworkPropertyMetadata speedMetadata = new FrameworkPropertyMetadata(0, null, CoerceSpeed);
            SpeedProperty = DependencyProperty.Register("Speed", typeof (int), typeof (Car), speedMetadata,
                                                        ValidateSpeed);

            //configure and register min speed property
            FrameworkPropertyMetadata minMetadata = new FrameworkPropertyMetadata(0, OnMinSpeedChanged);
            MinSpeedProperty = DependencyProperty.Register("MinSpeed", typeof (int), typeof (Car), minMetadata,
                                                           ValidateSpeed);

            //configure and register max speed property
            FrameworkPropertyMetadata maxMetadata = new FrameworkPropertyMetadata(1,OnMaxSpeedChanged, CoerceMaxSpeed);
            MaxSpeedProperty = DependencyProperty.Register("MaxSpeed", typeof (int), typeof (Car), maxMetadata,
                                                           ValidateSpeed);
        }

        #region Validate methods

        public static bool ValidateSpeed(object value)
        {
            Trace.WriteLine("ValidateSpeed");
            int speed = (int)value;
            return speed >= 0;
        }

        #endregion

        #region Coerce methods

        /// <summary>
        /// method for adjusting the speed according to the min and max
        /// </summary>
        /// <param name="d"></param>
        /// <param name="baseValue"></param>
        /// <returns></returns>
        public static object CoerceSpeed(DependencyObject d, object baseValue)
        {
            Trace.WriteLine("CoerceSpeed");
            Car car = (Car)d;
            int speed = (int)baseValue;
            //the speed can't be lower than the min speed
            speed = Math.Max(car.MinSpeed, speed);
            //the speed can't be greater than the max speed
            speed = Math.Min(car.MaxSpeed, speed);
            return speed;
        }

        /// <summary>
        /// method for adjusting the max speed according to me min speed.
        /// </summary>
        /// <param name="d"></param>
        /// <param name="baseValue"></param>
        /// <returns></returns>
        public static object CoerceMaxSpeed(DependencyObject d, object baseValue)
        {
            Trace.WriteLine("CoerceMaxSpeed");
            Car car = (Car)d;
            int maxSpeed = (int) baseValue;
            //the max speed can't be lower than the main speed
            return Math.Max(car.MinSpeed, maxSpeed);
        }

        #endregion

        #region Property changed methods

        /// <summary>
        /// this method is fired when the MaxSpeedProperty is changed
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        private static void OnMaxSpeedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Trace.WriteLine("OnMaxSpeedChanged");
            Car car = (Car)d;
            car.CoerceValue(SpeedProperty);
        }

        /// <summary>
        /// this method is fired when the MinSpeedProperty is changed
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        private static void OnMinSpeedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Trace.WriteLine("OnMinSpeedChanged");
            Car car = (Car)d;
            //coerce the max speed to ajdust to the new min speed
            car.CoerceValue(MaxSpeedProperty);
            //coerce the speed to adjust to the new min speed
            car.CoerceValue(SpeedProperty);
        }

        #endregion

    }

We can create an instance of the Car class in the initialization method of any window you like. Here is the my test code:

Car car = new Car();
Trace.WriteLine(string.Format("Speed:{0} Min:{1} Max:{2}",car.Speed,car.MinSpeed,car.MaxSpeed));
Trace.WriteLine(string.Format("Speed LocalValue:{0} EffectiveValue:{1}", car.ReadLocalValue(Car.SpeedProperty),
                car.GetValue(Car.SpeedProperty)));
car.Speed = 60;
Trace.WriteLine(string.Format("Speed: {0} Min:{1} Max:{2}",car.Speed,car.MinSpeed,car.MaxSpeed));
Trace.WriteLine(string.Format("Speed LocalValue:{0} EffectiveValue:{1}", car.ReadLocalValue(Car.SpeedProperty),
                car.GetValue(Car.SpeedProperty))); 
car.MinSpeed = 40;
Trace.WriteLine(string.Format("Speed: {0} Min:{1} Max:{2}",car.Speed,car.MinSpeed,car.MaxSpeed));
Trace.WriteLine(string.Format("Speed LocalValue:{0} EffectiveValue:{1}", car.ReadLocalValue(Car.SpeedProperty),
                car.GetValue(Car.SpeedProperty))); 
car.MaxSpeed = 80;
Trace.WriteLine(string.Format("Speed: {0} Min:{1} Max:{2}",car.Speed,car.MinSpeed,car.MaxSpeed));
Trace.WriteLine(string.Format("Speed LocalValue:{0} EffectiveValue:{1}", car.ReadLocalValue(Car.SpeedProperty),
                car.GetValue(Car.SpeedProperty)));

When you run this code you get the following output showing the order in which the methods were called:

Static Constructor
ValidateSpeed
ValidateSpeed
ValidateSpeed
ValidateSpeed
ValidateSpeed
ValidateSpeed
Speed:0 Min:0 Max:1
Speed LocalValue:{DependencyProperty.UnsetValue} EffectiveValue:0
ValidateSpeed
CoerceSpeed
ValidateSpeed
Speed: 1 Min:0 Max:1
Speed LocalValue:60 EffectiveValue:1
ValidateSpeed
OnMinSpeedChanged
CoerceMaxSpeed
ValidateSpeed
OnMaxSpeedChanged
CoerceSpeed
ValidateSpeed
CoerceSpeed
ValidateSpeed
Speed: 40 Min:40 Max:40
Speed LocalValue:60 EffectiveValue:40
ValidateSpeed
CoerceMaxSpeed
OnMaxSpeedChanged
CoerceSpeed
Speed: 60 Min:40 Max:80
Speed LocalValue:60 EffectiveValue:60

I hope this was usefull.

How to Learn WPF

I have been studying WPF more seriously for about two months. It is an amazing technology with a lot of new concepts that may be hard to grasp at first. In order to help others that may be trying to learnWPF and don't know where to start here is my take on it.

Although there is a lot of good material on the Internet the best way to learn (in my opinion) is still a good book. I have browsed through few books:

I found that the best one to get started with WPF and to read from cover to cover is Essential Windows Presentation Foundation by Chris Anderson. It is a relatively short book with about 500 pages. You will find that it is really easy to read with good examples and direct explanations. I have to say though that this book is not a good reference book. Don't let the fact that this is a 2007 book scare you away, this one is all about concepts and those didn't change since version 3.0 of the framework.

The other book I really liked was Pro WPF in C# 2008. This one is a in depth dive into WPF and maybe is not the book you would want to get started with. On the other hand this is the best reference book. It is really easy to browse since it has a dedicated chapter for each topic. Actually, this is the only book among the ones I looked at that has this format. The other books try to group related topics in the same chapter, which makes a good read but harder tolookup a specific thing.

The other book I would recommend is Windows Presentation Unleashed. It has an in depth coverage of all topics and is really easy to understand. The only thing I have against it is that it is a bit outdated since it was written for the framework 3.o. I wouldn't by this one but if you have someone you can borough from then I guess it isok.

There is also really good material on the MSDN site. Many of the books I mentioned before are heavily based on this documentation. The books are still more friendly to read but if you are looking any one topic in special the MSDN documentation is a really good place to search. Here is the link.

After you have a clear understanding on concepts such as Dependency Properties, Routed Events, Commands and Binding you have to look atMVVM concepts. This makes WPF even more amazing. I recommend getting started with Josh Smith's article on the MSDN Magazine called WPF Apps with The Model-View-ViewModel Design Pattern. Also make sure you follow the WPF Disciples.

If you are the screencast type of guy (or gal) you can checkout a lot of great videos on the WindowsClient.net site. Make sure you go to the Learn section.

Well, I think that is it. I'll update this post if I remember anything else but for now I think that this is plenty of material for you to get on your way to becoming aWPF master :-).

How to keep two ScrollViewers in Sync in WPF

As I got to know WPF, one of the features that I really like was the ability to bind the value of one control to the value of another one. Well, the other day I had a situation where I had 2 ScrollViewers side by side and I wanted to the two of them to be in sync. So, if I used the scrollbar one the left one I'd like the one on the right to scroll by the same increment. My first thought was then to bind the value of the offset of the scrollbars, that would be simple right? Not. The offset property is readonly. The way around this is really simple, you need you use the ScrollChanged event and in that event you use the method ScrollToVerticalOffset to move the ScrollBar of the other ScrollViewer.

Here is an example where I have a window with two ScrollViewers, each one has a ListBox with 7 items inside. As you scroll on the left side scroll viewer to see all the items in the ListBox you will notice that the ScrollViewer on the right will follow.

<Window x:Class="WpfScrollbarSync.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="100" Width="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>
        <ScrollViewer Grid.Column="0" Name="scrollViewerLeft" ScrollChanged="scrollViewerLeft_ScrollChanged">
            <ListBox>
                <ListBoxItem>1</ListBoxItem>
                <ListBoxItem>2</ListBoxItem>
                <ListBoxItem>3</ListBoxItem>
                <ListBoxItem>4</ListBoxItem>
                <ListBoxItem>5</ListBoxItem>
                <ListBoxItem>6</ListBoxItem>
                <ListBoxItem>7</ListBoxItem>
            </ListBox>
        </ScrollViewer>
        <ScrollViewer Grid.Column="1" Name="scrollViewerRight">
            <ListBox>
                <ListBoxItem>1</ListBoxItem>
                <ListBoxItem>2</ListBoxItem>
                <ListBoxItem>3</ListBoxItem>
                <ListBoxItem>4</ListBoxItem>
                <ListBoxItem>5</ListBoxItem>
                <ListBoxItem>6</ListBoxItem>
                <ListBoxItem>7</ListBoxItem>
            </ListBox>
        </ScrollViewer>
    </Grid>
</Window>

And here is the codebehind:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    private void scrollViewerLeft_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        scrollViewerRight.ScrollToVerticalOffset((sender as ScrollViewer).VerticalOffset);
    }
}

I hope this can save someone one minute or two. :-)

wpf