Showing posts with label asynchronous binding. Show all posts
Showing posts with label asynchronous binding. Show all posts

Sunday, August 14, 2011

Silverlight 5 Beta - Relative Source Binding

In this post we will be discussing another new feature of Silverlight 5 Beta. It is Relative Source binding. RelativeSource has long been missing from Silverlight. It has always been there in WPF. Silverlight 5 is currently available in Beta and can be downloaded from here:

http://www.microsoft.com/download/en/details.aspx?id=23887

Let's create a MVVM Light Silverlight application AppSilverlightRelativeSourceBinding. It would have a list of students on display. The user should be allowed to remove any student on the list. In order to see the application of Relative Source binding, we would see how we can bind the Command on the child element to a parent element. Actually, the Remove button on child view should be bound to a Command in the DataContext of a parent element in the hierarchy [UserControl].


Just make sure that you have Silverlight 5 version selected in the project's properties.


This view model is the Main view model of the application. It has a collection of students (StudentViewModel). Since the collection is an ObservableCollection, all the addition / removal of elements in the collection would directly reflected in the view. It also has a Command which removes the student from the collection. This is the Command which would be bound by child elements.
namespace AppSilverlightRelativeSourceBinding.ViewModel
{
    using GalaSoft.MvvmLight;
    using System.Collections.ObjectModel;
    using GalaSoft.MvvmLight.Command;

    public class MainViewModel : ViewModelBase
    {
        #region Properties

        public string Welcome
        {
            get
            {
                return "Silverlight 5 Beta - Relative Source Binding";
            }
        }

        ObservableCollection<StudentViewModel> _students;
        public ObservableCollection<StudentViewModel> Students
        {
            get
            {
                if (_students == null)
                {
                    _students = new ObservableCollection<StudentViewModel>();

                    _students.Add(new StudentViewModel() { StudentFirstName = "Kamran", StudentLastName = "Khan" });
                    _students.Add(new StudentViewModel() { StudentFirstName = "Asad", StudentLastName = "Hussain" });
                    _students.Add(new StudentViewModel() { StudentFirstName = "Faisal", StudentLastName = "Lashari" });
                    _students.Add(new StudentViewModel() { StudentFirstName = "Hyder", StudentLastName = "Baloch" });
                    _students.Add(new StudentViewModel() { StudentFirstName = "Baber", StudentLastName = "Chaudhari" });
                }
                return _students;
            }
        }

        #endregion

        #region Commands

        RelayCommand<StudentViewModel> _removeStudentCommand;
        public RelayCommand<StudentViewModel> RemoveStudentCommand
        {
            get
            {
                return _removeStudentCommand ??
                        new RelayCommand<StudentViewModel>((student) =>
                        {
                            if (this.Students.Contains(student))
                            {
                                this.Students.Remove(student);
                            }
                        });
            }
        }

        #endregion        
    }
}

The definition of StudentViewModel used above is as follows:
namespace AppSilverlightRelativeSourceBinding.ViewModel
{   
    using GalaSoft.MvvmLight;

    public class StudentViewModel : ViewModelBase
    {
        #region Notifiable Properties

        string _studentLastName;
        public string StudentLastName
        {
            get { return _studentLastName; }
            set
            {
                _studentLastName = value;
                RaisePropertyChanged("StudentLastName");
            }
        }

        string _studentFirstName;
        public string StudentFirstName
        {
            get { return _studentFirstName; }
            set
            {
                _studentFirstName = value;
                RaisePropertyChanged("StudentFirstName");
            }
        }

        #endregion

    }
}
It simply has two properties for first and last names of a student. The view model inherits from ViewModelBase which is provided by MVVM Light toolkit. Now let's see how we can display this view model. It is an implicit DataTemplate to show the student. The first and last names are displayed in a TextBlock. It also has a Remove button. Clicking the button would delete the student from the collection. Since StudentViewModel has no idea about which collection it has been part of and it has to be handled by something which holds this collection. So the button's Command needs to be bound to MainViewModel. This is why Relative Source binding makes most sense to be used here. Let's define this DataTemplate in MainSkin.xaml resource dictionary provided by MVVM Light.
<DataTemplate DataType="vm:StudentViewModel" >
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="30" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Button Content="Remove" Grid.Column="0"                       
                CommandParameter="{Binding}" >                
            <Button.Command>
                <Binding RelativeSource="{RelativeSource AncestorType=UserControl}" 
                         Path="DataContext.RemoveStudentCommand" />
            </Button.Command>
        </Button>
        <Border Grid.Column="1" />
        <Grid Grid.Column="2" >
            <TextBlock>  
                <Run Text="{Binding StudentLastName}" FontWeight="Bold" />
                <Run>
                    <Run.Text>
                        <Binding Path="StudentFirstName" StringFormat=",{0}" />
                    </Run.Text>
                    </Run>
            </TextBlock>
        </Grid>
    </Grid>
</DataTemplate>
We need to include this namespace in the above resource dictionary.
xmlns:vm="clr-namespace:AppSilverlightRelativeSourceBinding.ViewModel"
Now the design of MainPage is simple enough. Mainly it has a ListBox to display the collection of StudentViewModel. Since MainSkin.xaml resource dictionary is merged here, the implicit DataTemplate is automatically applied.
<UserControl x:Class="AppSilverlightRelativeSourceBinding.MainPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"            
             DataContext="{Binding Main, Source={StaticResource Locator}}">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Skins/MainSkin.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBlock FontSize="36" Grid.Row="0"
                   FontWeight="Bold"
                   Foreground="Purple"
                   Text="{Binding Welcome}"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center"
                   TextWrapping="Wrap" />
        <ListBox ItemsSource="{Binding Students}"
                 Grid.Row="1" />
    </Grid>
</UserControl>
When we run the application, the application is loaded as follows:


Download Code:

Wednesday, January 26, 2011

WPF - Performance Improvement for MVVM Applications - Part # 1

This is a series of posts about performance improvements of an MVVM based applications. You can find the other posts here:

- Part 2 : http://shujaatsiddiqi.blogspot.com/2011/02/wpf-performance-improvement-for-mvvm.html

- Part 3: http://shujaatsiddiqi.blogspot.com/2011/03/wpf-performance-improvement-for-mvvm.html

In this example we are discussing the various performance improvement for a WPF Binding developed using MVVM. This is for enhancing user experience by increasing the responsiveness of the system. MVVM based application is highly dependent upon the WPF Binding system. I think if we use certain features of Binding system then we can achieve this.
<Window x:Class="WpfApplication_ASync_Binding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication_ASync_Binding"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<TextBlock  Height="56" HorizontalAlignment="Left"
Margin="40,71,0,0" Name="label1" VerticalAlignment="Top"
Width="434" Background="Aquamarine" >
<TextBlock.Text>
<Binding Path="StudentName" StringFormat="testtt:{0}" />
</TextBlock.Text>
</TextBlock>
</Grid>
</Window>

We are not changing the code behind of the view so it should be as created by default. The view model:
namespace WpfApplication_ASync_Binding
{
using System.ComponentModel;

class MainWindowViewModel : INotifyPropertyChanged
{
private Student _student;
public MainWindowViewModel()
{
_student = new Student();
} 

private string _studentName;
public string StudentName
{
get
{
return _student.StudentName;
}
set
{
_student.StudentName = value;
OnPropertyChanged(StudentName);
}
} 

public event PropertyChangedEventHandler PropertyChanged; 

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

The view model is using _student as model. This is an instance of Student class. As you can see StudentName is just a proxy property for the model’s property named StudentName. The definition of Student is as follows:
namespace WpfApplication_ASync_Binding
{
class Student
{
public string StudentName { get; set; } 

public Student()
{
StudentName = "Muhammad";
}
}
}

Let’s run this application. The output should appear as follows:


Now let’s change this a bit. Let’s consider Student is using some complex logic for its property StudentName. It might be using a web service which might be slow. Now since we are using proxy property for binding this delay would slow down the binding and the form would become idle. Let’s create this scenarios by just introducing a delay using Thread.Sleep() as follows:
namespace WpfApplication_ASync_Binding
{
class Student
{
private string _studentName;
public string StudentName
{
get
{
//imaginary delay
Thread.Sleep(10000);
return _studentName;
}
set { _studentName = value; }
}

public Student()
{
StudentName = "Muhammad";
}
}
}

Now run the application. The same form would display but after a delay of atleast 10 seconds.

Basically when Binding system would access the getter for StudentName property in the DataContext. It would be delayed because the view model would be trying to get the Model’s property resulting in a delay of atleast 10 seconds (because of Thread.Sleep). So form instance is created. It assigns the DataContext as MainWindowViewModel in InitializeComponent. When it attempts to bind the Text property of TextBlock. It experiences this delay. So the delay is because of binding. If this binding becomes asynchronous then the performance could improve. You should be glad to learn that WPF Binding system supports making its binding asynchronous by providing IsAsync property in Binding markup extension. Let’s use this!

We update the view as follows:
<TextBlock.Text>
<Binding Path="StudentName" StringFormat="testtt:{0}" IsAsync="True" />
</TextBlock.Text>

Now run this. The form appears as follows:


This would be shown like this for atleast 10 seconds. During this time, it starts a ThreadPool thread on the background to get the Binding source. As soon as the source property becomes available, the binding updates the view as follows:


Well this is good but user sees nothing on the screen for atleast 10 seconds. We might want to show something else to the user until the data becomes available as a fallback mechanism. WPF binding system supports that too. You can achieve that by setting FallBackValue propery of Binding as follows:
<TextBlock.Text>
<Binding Path="StudentName" StringFormat="testtt:{0}"
IsAsync="True" FallbackValue="Test Fallback value" />   
</TextBlock.Text

Now run the application. The window is shown as follows:


This is shown like that for 10 seconds showing the Fallback value for Binding. You can see that StringFormat is not applied for FallbackValue. After 10 seconds, it updates itself as follows:


In order to have more sophisticated fallback mechanism, you might want to consider Priority Binding.

http://shujaatsiddiqi.blogspot.com/2010/09/wpf-priority-binding.html

The world is not simple. Let’s make it a little complex by updating the constructor of our model (Student) as follows:
public Student()
{
StudentName = "Muhammad";
Thread.Sleep(20000);
}

This is to simulate the 20 seconds further delay in Binding. Let’s run the application. For 20 seconds, nothing appears on the screen. After that the window appears with the fallback value. The fallback value remains on the view for 10 seconds. After that the view is updated with the finalized value for StudentName with applied StringFormat. Now the main question is why this window appears after 20 seconds when binding is asynchronous. Basically Binding.IsAsync just makes the Binding asynchronous. If there is a delay in the construction of DataContext, this would still be on the UI thread hence synchronous. The construction of DataContext (MainWindowViewModel) is causing this delay because of delay of instantiation of the Student (model) in the constructor of view model [Thread.Sleep(20000)].

In order to improve this behavior we can update the way DataContext is constructed. We can construct the object using ObjectDataProvider. This is to utilize the asynchronous instantiation feature of ObjectDataProvider. We can cause asynchronous construction by setting IsAsynchronous for ObjectDataProvider. Let’s update the definition of the section of XAML for view where we are assigning DataContext as follows:
<Window.DataContext>
<ObjectDataProvider ObjectType="{x:Type local:MainWindowViewModel}" IsAsynchronous="True"  />
</Window.DataContext>

Now run the application. As we run the application there is no delay and the following screen appears:


This is maintained for 30 seconds. The 20 seconds is for the construction of DataContext (causing construction of model) and the other 10 seconds is for the delay in the getter for StudentName property from DataContext. Basically the Fallback value is maintained until the value is available no matter the delay is called by the DataContext construction or the available of its property.

10 + 20 = 30 seconds

Eventually the window is updated as follows:


Download:

Monday, November 29, 2010

WPF - Dispatcher.Invoke is an overkill

In this post we discuss that executing a synchronous operation on UI threads can be an overkill. It should only be used with care. As we know, we can use Invoke and BeginInvoke on Dispatcher to execute a synchronous and asynchronous operation on UI thread respectively. Calling Invoke is an overkill.

In order to discuss this point. Let us use both, Invoke and BeginInvoke, in a sample WPF application. The following is a WPF window with two text boxes and a button.

<Window x:Class="WpfDispatcher_OperationInvocation.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="451">
<Grid>
<TextBox Height="30" Margin="175,24,30,0" Name="textBoxInvoke" VerticalAlignment="Top" />
<TextBox Height="30" Margin="175,79,30,0" Name="textBoxBeginInvoke" VerticalAlignment="Top" />
<Label Margin="14,24,0,0" Name="label1" Height="24" HorizontalAlignment="Left"
VerticalAlignment="Top" Width="133">Updated Through Invoke</Label>
<Label Height="32" HorizontalAlignment="Left" Margin="9,77,0,0" Name="label2"
VerticalAlignment="Top" Width="165">Updated Through Begin Invoke</Label>
<Button Height="32" Margin="128,0,146,82" Name="button1" VerticalAlignment="Bottom"
Click="button1_Click" >Update Text</Button>
</Grid>
</Window>

As you can see above, we have two textboxes and a button. We have also specified button1_Click as the Click handler for button1. We are using Invoke for one operation on UI thread and BeginInvoke for other. In both these operations, we are updating the text of one of the text boxes.

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

void button1_Click(object sender, RoutedEventArgs e)
{
Thread t = new Thread(
() =>
{
textBoxInvoke.Dispatcher.Invoke(
new Action(() => textBoxInvoke.Text = "Updated"));

textBoxBeginInvoke.Dispatcher.BeginInvoke(
new Action(() => textBoxBeginInvoke.Text = "Updated"));
});

t.IsBackground = true;
t.Start();
}
}

Whenever we call Invoke or BeginInvoke on a Dispatcher, we are introducing a new work item in the dispatcher queue of the dispatcher. So what is the difference between the two? The answer is that Invoke is a synchronous operation and BeginInvoke is an asynchronous operation.

When we call BeginInvoke on a Dispatcher, it pushes the work item on the queue and returns (1 in above figure) DispatcherOperation which can be used to keep on eye on the status of the execution of the delegate. The calling thread wouldn't wait for anything and goes on any other tasks (2 in above figure). On the other side, Invoke causes the work item to be pushed on the queue. It is pushed based on its DispatcherPriority. Now the calling thread is waiting for this operation to be completed. The work item keeps waiting on the Dispatcher queue when there comes her turn of execution by Dispatcher. The dispatcher executes it. Now the result is returned to the calling thread. There might be many work items in the dispatcher queue with same or greater priority values. Calling an operation like this is lethal for the calling thread cause it could be waiting for a long time.


But there might be certainly situations when you can not go without going synchronous. In the following example, we need the text entered in a text box and show it in a MessageBox.

string enteredText = "";

textBox1.Dispatcher.Invoke(new Action(() => enteredText = textBox1.Text), null);
MessageBox.Show(enteredText);

If we don't call this synchronously then we by the time we reach MessageBox.Show this item hasn't been executed by textBox1's Dispatcher so the text is not yet copied to winTitle so would be showing an empty MessageBox.

We can still wait on work item introduced in Dispatcher using BeginInvoke. Basically BeginInvoke does not have a corresponding “EndInvoke”. Many a times we need to find out when an operation ended before starting another dependent work item. BeginInvoke returns a DispatcherOperation. We can use Status property of DispatcherOperation to find this out. If it is Completed then the dispatcher is done executing this operation and we can go ahead with executing the dependent work item. We can also call Wait() on DispatcherOperation which makes this operation as synchronous which is similar to calling Invoke on Dispatcher. We need to be careful as this can lead to the same issue of deadlock as Invoke when UI and worker thread are waiting for some resource which one is needing and the other has it. DispatcherOperation also supports aborting a work item. When we abort it then it is removed from dispatcher’s queue. It’s state is set as Aborted.
DispatcherOperation dispatcherOperation = 
textBoxBeginInvoke.Dispatcher.BeginInvoke(
new Action(() => textBoxBeginInvoke.Text = "Updated"));

//Any other Task(s)

if (dispatcherOperation.Status != DispatcherOperationStatus.Completed)
{
dispatcherOperation.Wait();
}


Now the last words! Avoid using Invoke on Dispatcher when we are absolutely not sure that we need it, otherwise, use BeginInvoke if it wouldn't be making any difference.

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