Thursday, September 9, 2010

WPF Priority Binding

With Priority binding, we define a list of bindings arranged in the order of their priorities from top to bottom. The bounded property gets the data from these bindings in this very priority order. The first bindng which gets the data for binding is considered to be the active binding. So the user has some data on the view as soon as the data from first binding becomes available.

The greatest thing is that it doesn't stop there when first data is loaded. If after loading first data, data from any binding higher in the priority list becomes available then WPF uses data from this binding instead.

Lets see a small example in which we use this feature of WPF Binding. Priority Binding is defined for Text property of TextBox. It is bound to any of the three properties from the DataContext including FastValue, MediumValue and SlowValue. When we define priority binding, the first binding is considered to be one with the highest priority. The priorities decrease as we move down.
<Window x:Class="WpfApplicationASynchBinding.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplicationASynchBinding"
DataContext ="{DynamicResource ViewModel}"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<local:Window1ViewModel x:Key="ViewModel" />
</Window.Resources>
<Grid>
<TextBlock Width="200" Height="100" >
<TextBlock.Text>
<PriorityBinding>
<Binding Path="SlowValue" IsAsync="True" />
<Binding Path="MediumValue" IsAsync="True" />
<Binding Path="FastValue" IsAsync="True" />
</PriorityBinding>
</TextBlock.Text>
</TextBlock>
</Grid>
</Window>

Now we define the view model which is used as the data context for the above window. You can see that we have defined the three properties as expected by the above view (FastValue, MediumValue and SlowValue). To create the delay effect, we have used Thread.Sleep().

class Window1ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

string _slowValue = "Slow Value";
public string SlowValue
{
get
{
Thread.Sleep(10000);
return _slowValue;
}
set
{
_slowValue = value;
onPropertyChanged("SlowValue");
}
}

string _mediumValue = "Medium Value";
public string MediumValue
{
get
{
Thread.Sleep(5000);
return _mediumValue;
}
set
{
_mediumValue = value;
onPropertyChanged("MediumValue");
}
}

string _fastValue = "Fast Value";
public string FastValue
{
get
{
Thread.Sleep(2000);
return _fastValue;
}
set
{
_fastValue = value;
onPropertyChanged("FastValue");
}
}


private void onPropertyChanged(string fieldName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(fieldName));
}
}
}

When we run the application, it appears as follows at first:



After 5 seconds, the data from MediumValue becomes available. So it is used by the WPF Binding System. It is assigned to the Text property of the text box.



After 10 seconds, the data from the slowest binding with the highest priority becomes available, so it used now.



Note:
If data from the bindings with different priorities becomes available at the same time then still the data from the binding with highest priority is utilized. In the above example if we had defined a property SlowestValue with the same delay as SlowValue then

No comments: