Monday, February 17, 2014

Simple ObservableCollection WPF MVVM example

Using ObservableCollection has its benefit. Whenever any element changes (added, deleted or updated or entire list being replaced) within the ObservableCollection instatnce, the bound UI element automatically reflects the changes.


If you would like to know more details of ObservableCollection, please read from the API link below.

http://msdn.microsoft.com/en-us/library/ms668604%28v=vs.110%29.aspx


We can use ObservableCollection object and bindable property in a View Model class and bind this to a UI control such as DataGrid's ItemsSource property. Whenever anything changes in the ObservableCollection, bound grid will automatically reflect the changes in the UI.

ViewModel class as follows:



    public class TradesViewModel : BaseViewModel, ITradeViewModel
    {
        private ObservableCollection<Trade> _trades = new ObservableCollection<Trade>();

        private ICommand _saveCommand;
        private ICommand _loadCommand;

        public TradesViewModel()
        {
            _saveCommand = new SaveTradesCommand();
            _loadCommand = new LoadTradesCommand();
            _trades = GetTrades();
        }

        public ObservableCollection<Trade> Trades { get {return _trades;} }

        public ObservableCollection<Trade> GetTrades()
        {
            if (_trades == null || _trades.Count == 0)
                _loadCommand.Execute(_trades);
            return _trades;
        }
    }



Lets say _loadCommand's code populates the _trades ( ObservableCollection). For demonstrating live updates we have made a infinite loop in the loading where every 2 seconds it loads new trades with quantity and price being different. Below is the code loading trades data every 2 seconds.



public void Execute(object parameter)
        {
            var loadedTrades = parameter as ObservableCollection<Trade>;
            if (loadedTrades != null)
            {
                TaskFactory taskfac = new TaskFactory();
                taskfac.StartNew(() =>
                    {
                        while (true)
                        {
                            var tradelist = Trades.LoadTradesFromDataSource();
                            App.Current.Dispatcher.Invoke(new Action(() =>
                            {
                                loadedTrades.Clear();
                                foreach (var trade in tradelist)
                                    loadedTrades.Add(trade);
                            }));

                            Thread.Sleep(2000);
                        }
                    });
            }
        }


Trade and load trades code:



public class Trade : ITrade   
{
        private string _qty;
        public string Side { get; set; }
        public string Ticker { get; set; }
        public string Qty { get; set; }
        public string Price { get; set; }
        public string Trader { get; set; }
        public string Sales { get; set; }
       }





public class Trades
       {
        public static IEnumerable<Trade> LoadTradesFromDataSource()
        {
            var pricetmp = DateTime.Now.Second; // just to get some number
            var qtytmp = (DateTime.Now.Second + 5) * 1000; // just to get some
number

            return new List<Trade>()
            {
                new Trade(){Side="B", Price=pricetmp.ToString(), Ticker="aol",
Trader="tom", Sales="harry", Qty=qtytmp.ToString()},
                new Trade(){Side="B", Price=pricetmp.ToString(), Ticker="gm",
Trader="tom", Sales="harry", Qty=qtytmp.ToString()},
                new Trade(){Side="B", Price=pricetmp.ToString(), Ticker="ge",
Trader="tom", Sales="harry", Qty=qtytmp.ToString()},
            };
        }
       }



XAML code as below binds the ItemsSource property of the DataGrid to our ViewModel's ObservableCollection property called Trades.


<Grid.DataContext>
            <viewmodel:TradesViewModel/>
        </Grid.DataContext>
        <DataGrid
                AutoGenerateColumns="True"
                HorizontalAlignment="Stretch" Name="dataGrid1" VerticalAlignment="Top"
                ItemsSource="{Binding Trades}"
                />


When we run this application, we see a window coming up with trades populated like below:




and every two seconds it will automatically show new trades data like below:




So as soon as the ObservableCollection data is being updated it is reflecting real-time on the DataGrid.


Notice three things:

Notice 1: I created a new "task" to run the infinite loop to update data every two seconds and therefore had to update using App.Current.Dispatcher.Invoke since ObservableCollection object was instantiated in UI thread. (see details here http://wpfgrid.blogspot.com/2014/02/wpf-using-dispatcher-in-viewmodel.html)

Notice 2:
Also if we simply make _trades = new ObservableCollection ...  it will not wok. Rather we need to clear the collection and add new instances of Trade objects.

Notice 3:
Since in this exmaple (only) we are replacing the enter list (by clearing and add all elements), we did not need to implement INotofyPropertyChanged niterface in "Trade" class. However, we should implement that interface in Trade class and have each property raise property changed event, that way when any property value changes (instead of entire list being changed as shown in this example), it will reflect the change of that particular cell in the DataGrid automatically.


DOWNLOAD CODE

Codes for this simple exmaple can be downloaded from my skydrive here:
https://skydrive.live.com/?mkt=en-US#cid=BA4BC1E3D681B9B3&id=BA4BC1E3D681B9B3!105
Called: SimpleObservableCollectionWPFExample.zip




WPF - Using Dispatcher in ViewModel

There are times when we need to delegate a block of codes through dispatcher. If the code is in code behind of a window's or usercontrol's code then it is simple because then we can just call this.Dispatcher.Invoke to pass the code block. However what if the code is in the ViewModel. In order to use the MVVM pattern we should in fact put code in view model and avoid coding in code behind file.

So when there is a need to execute code in UI thread, we should use dispatcher as

App.Current.Dispatcher.Invoke.


If UI thread executing codes in view model, there is no need to use delegate (though dispatcher invoke). However if code in view model is being executed in another thread other than the UI thread and if it is updating any object that was created in UI thread, then we need to execute this code (one in another thread) through a dispatcher delegate in order to update object that was created in UI thread.

For example, let us say we are updating an ObservableCollection object that was instantiated in UI thread and then we created a "task" and within which we are trying to update that ObservableCollection object.

public ObservableCollection<Trade> LoadedTrades = new ObservableCollection<Trade>();

public void LoadTradesData()
{
            TaskFactory taskfac = new TaskFactory();
            taskfac.StartNew(() =>
                {
                        var tradelist = Trades.LoadTradesFromDataSource();
                        App.Current.Dispatcher.Invoke(new Action(() =>
                        {
                            LoadedTrades.Clear();
                            foreach (var trade in tradelist)
                                LoadedTrades.Add(trade);
                        }));
                });

}

Friday, December 13, 2013

Saturday, November 30, 2013

Prism, WPF and Unity based modular application step by step

http://www.codeproject.com/script/Articles/ArticleVersion.aspx?waid=103435&aid=690475

Exception Validation in WPF

By default WPF provides validation control template which displays red border around the control whose input is being validated.

There are two simple ways one can indicate validation error due to exception.

             

<Binding.ValidatesOnExceptions>True</Binding.ValidatesOnExceptions>


Or by specifying ValidatingRules and including an instance of built-in ExceptionValidationRule.

                    <Binding.ValidationRules>
                        <ExceptionValidationRule></ExceptionValidationRule>
                    </Binding.ValidationRules>