Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use DomainContext.Load to populate properties of my ViewModel?

I have a Silverlight page that gets its data from a view model class which aggregates some data from various (RIA services) domain services.

Ideally I'd like the page to be able to data bind its controls to properties of the view model object, but because DomainContext.Load executes a query asynchronously, the data is not available when the page loads.

My Silverlight page has the following XAML:

<navigation:Page x:Class="Demo.UI.Pages.WidgetPage" 
               // the usual xmlns stuff here...
               xmlns:local="clr-namespace:Demo.UI.Pages" mc:Ignorable="d"
               xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"

                d:DataContext="{d:DesignInstance Type=local:WidgetPageModel, IsDesignTimeCreatable=False}"

               d:DesignWidth="640" d:DesignHeight="480"
               Title="Widget Page">
        <Canvas x:Name="LayoutRoot">
            <ListBox ItemsSource="{Binding RedWidgets}" Width="150" Height="500" />
        </Canvas>
    </navigation:Page>

My ViewModel looks like this:

public class WidgetPageModel
{
    private WidgetDomainContext WidgetContext { get; set; }

    public WidgetPageModel()
    {          
        this.WidgetContext = new WidgetDomainContext();

        WidgetContext.Load(WidgetContext.GetAllWidgetsQuery(), false);            

    }

    public IEnumerable<Widget> RedWidgets
    {
        get
        {
            return this.WidgetContext.Widgets.Where(w => w.Colour == "Red");
        }
    }
}

I think this approach must be fundamentally wrong because the asynchronous nature of Load means that the widget list is not necessarily populated when the ListBox data binds. (A breakpoint in my repository shows that the code to populate to collection is being executed, but only after the page renders.)

Can someone please show me the right way to do this?

like image 673
kristian Avatar asked Jun 18 '10 00:06

kristian


1 Answers

The missing piece of the puzzle is that I needed to be raising events when the properties changed.

My updated ViewModel is as follows:

public class WidgetPageModel : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

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

    private WidgetDomainContext WidgetContext { get; set; }

    public WidgetPageModel()
    {          
        this.WidgetContext = new WidgetDomainContext();

        WidgetContext.Load(WidgetContext.GetAllWidgetsQuery(), 
            (result) =>
            {
                this.RedWidgets = this.WidgetContext.Widgets.Where(w => w.Colour == "Red");
            }, null);            

    }

    private IEnumerable<Widget> _redWidgets;
    public IEnumerable<Widget> RedWidgets
    {
        get
        {
            return _redWidgets;
        }
        set
        {
            if(value != _redWidgets)
            {
                _redWidgets = value;
                RaisePropertyChanged("RedWidgets");
            }
        }
    }
}

The controls bound to these properties are updated when the property change event fires.

like image 192
kristian Avatar answered Oct 09 '22 12:10

kristian