This project is read-only.

RIAService data load and binding

Jul 8, 2010 at 7:30 AM
Edited Jul 8, 2010 at 7:33 AM

I use RIAService as my data access way. now there is a View(WQ_MoniSectionListView.xaml) and a ViewModel(WQ_MoniSectionListViewModel.cs).

View:  use a listbox to bind the WQ_MoniSchemes.

<DataTemplate x:Key="SchemeItemTemplate">
            <TextBlock Text="{Binding scheme_name}" FontSize="12" Margin="2"></TextBlock>
        </DataTemplate>     

<ListBox x:Name="SchemeListBox"  ItemsSource="{Binding WQ_MoniSchemes}"
                         ItemTemplate="{StaticResource SchemeItemTemplate}"  >
</ListBox>

ViewModel:

use RIA to get the data from database. then store the data in MoniSchemes in two different case. you can find the code below.

and  in case 2, nothing bind to SchemeListBox. and when i set a debug breakpoint in "private  void loadOp_Completed(object sender, EventArgs e)".

WQ_MoniSchemes can get the value.

what's the problem?

 

[nRoute.ViewModels.MapViewModel(typeof(Mrjiou.ArcGIS.App.Views.WQ_MoniSectionListView))]
    public class WQ_MoniSectionListViewModel : nRoute.ViewModels.NavigationViewModelBase
    {
        public List<WQ_MoniScheme> WQ_MoniSchemes { get; private set; }
        private WQ_MoniSectionDomainContext wq_MoniSectionContext = new WQ_MoniSectionDomainContext();

        [nRoute.Components.Composition.ResolveConstructor]
        public WQ_MoniSectionListViewModel()
        {
            EntityQuery<WQ_MoniScheme> query = wq_MoniSectionContext.GetWQ_MoniSchemeQuery();
            LoadOperation<WQ_MoniScheme> loadOp = wq_MoniSectionContext.Load<WQ_MoniScheme>(
                query, LoadedCallback, null);
            loadOp.Completed += new EventHandler(loadOp_Completed);

            /*******************************************case1*********in this case WQ_MoniSchemes can be binded to the listbox correctly.*/
           WQ_MoniSchemes = loadOp.Entities.ToList<WQ_MoniScheme>();
            WQ_MoniScheme s = new WQ_MoniScheme();
            s.scheme_uid = Guid.NewGuid();
            s.scheme_name = "<All>";
            WQ_MoniSchemes.Add(s);
        }

        private  void loadOp_Completed(object sender, EventArgs e)
        {
            /*******************case2*******************in this case WQ_MoniSchemes can not be binded to the listbox, but the WQ_MoniScheme data has be added to the WQ_MoniSchemes*/
            WQ_MoniSchemes = (sender as LoadOperation<WQ_MoniScheme>).Entities.ToList<WQ_MoniScheme>();
            WQ_MoniScheme s = new WQ_MoniScheme();
            s.scheme_uid = Guid.NewGuid();
            s.scheme_name = "<All>";
            WQ_MoniSchemes.Add(s);
        }

}

 

thanks for this nroute project!

Jul 8, 2010 at 9:40 AM

First, you are welcome; second, I'm not 100% clear on your question but it seems to me the problem is that you are creating the second property post the binding stage, and thus you have to inform the binding engine that you have updated it - and you do so using the INotifyPropertyChanged interface (which NavigationViewModelBase implements). So quite simply just raise the property changed notification, say if you have SchemeA and SchemeB then use something like:

public WQ_MoniScheme SchemeA { get; private set; }

public WQ_MoniScheme SchemeB { get; private set; }

private  void loadOp_Completed(object sender, EventArgs e)
{    
    this.SchemeB = new WQ_MoniScheme();
    // update the scheme b here - then notify
    NotifyPropertyChanged(() => SchemeB);
}

Hope that helps,
Rishi 

 

Jul 8, 2010 at 9:49 AM

Sorry, I just realized you were adding to the collection - well, then instead of List<WQ_MoniScheme> use ObservableCollection<WQ_MoniScheme>. The principle is the same as what I mentioned earlier, the collection you are adding too needs to inform (post the initial binding stage) that it has been updated, and the observable collection does that by implementing INotifyCollectionChanged.

Cheers,
Rishi 

Jul 8, 2010 at 10:35 AM

thanks,i will have a try.

now i'm study at nroute. today i find that:

Trigger code:

<i:EventTrigger EventName="ItemClick">                                  
            <nRoute:ExecuteSiteMapNodeAction SiteMapNode="{Binding ClickedItem.DataContext, ElementName=AgMenu}"/>                
</i:EventTrigger>

Node code:  it's OK!

<nRoute:NavigationNode Title="1" Url="Views/WQ_MoniSectionListView/">

</nRoute:NavigationNode>

but if i change to this:

<nRoute:ControllerActionNode  Title="1" Url="Views/WQ_MoniSectionListView/">
                                    
</nRoute:ControllerActionNode>

it will post a error.  hehe .it's different.  as a beginner, it's a long way to study this, xixi :). good work, thanks !

 

 

Jul 9, 2010 at 12:21 PM

Well, you are getting an error because ControllerActions are equivalent to a navigable view, they are fundamentally different. ControllerActions are more like Url-addressable code-blocks (though they can do much more), for example:

[MapController("Content/Windows/{Action}/")]
public class WindowsController : Controller
{
    public void About()
    {
        var _window = new AboutWindow();
        _window.ShowDialog();
    }
}

You can now execute the code-block (from the UI or otherwise) in the About method by pointing to the "Content/Windows/About" Url. To learn more about this, read-up on ASP.NET MVC - this is based on the controller concept in MVC framework.

Cheers,
Rishi