views:

275

answers:

3

The problem we are having is that we cannot get binding to work in our prism silverlight application when using the view-model first approach. The view first approach work fine. We have gone over the official documentation and various web sites, but have still not resolved the issue. Below is the code for both the view-model first, and the view first approach. Are we missing something? Read about it on my blog http://silvercasts.blogspot.com

View-Model first approach:

Bootstrapper:

   internal void RegisterLoginRegionAndView()
   {
       IRegionManager regionManager = Container.Resolve<IRegionManager>();

       regionManager.RegisterViewWithRegion(ShellRegionNames.MainRegion,
       () => Container.Resolve<IViewModel>().View);
    }

ViewModel:

   public ViewModel(IView view)
   {
       View = view;
       View.SetModel(this);

       User = new User();
       User.Username = "TestUser";
   }

ViewModel Interface:

 public interface IViewModel
   {
       IView View { get; set; }
   }

View Interface:

public interface IView
   {
       void SetModel(IViewModel model);
   }

View Xaml:

 <TextBox x:Name="Username" TextWrapping="Wrap" Text="{Binding User.Username}" />

View Code Behind:

public void SetModel(IViewModel viewModel)
   {
       this.DataContext = viewModel;
   }

View first approach

Bootstrapper:

regionManager.RegisterViewWithRegion(ShellRegionNames.MainRegion, typeof(IView));

ViewModel:

  public ViewModel()
   {
       User = new User();
       User.Username = "TestUser";
   }

View Code Behind:

public View(IViewModel viewModel)
   {
       InitializeComponent();
       this.DataContext = viewModel;
   }
A: 

The obvious difference to me is that you set the DataContext in the "view first" approach, but not in the "view model first" approach. I'm not sure if Prism sets the DataContext for you (I'd guess that you're assuming that it does) but try setting the DataContext manually to see if this is the problem. In your ViewModel constructor you call View.SetModel(this) - does that call set the DataContext?

James Cadd
+1  A: 

Your implementation of SetModel on your view needs to be as follows:

public void MyUserControl : UserControl, IView
{
     //...
     public void SetModel(IViewModel vm)
     {
          this.DataContext = vm;
     }
}

If that's not there, it needs to be (you haven't posted your implementation of SetModel, but this would be the source of the issue in this case).

If this is not the issue, it's likely because your ViewModel does not implement INotifyPropertyChanged. I usually use a base ViewModel that does this:

public class ViewModelBase : INotifyPropertyChanged
{
     public event PropertyChangedEventHandler PropertyChanged;
     public void OnPropertyChanged(string propertyName)
     {
          if(PropertyChanged != null)
          {
               PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
          }
     }
}

And then all of my ViewModels derive from that:

public class MyViewModel : ViewModelBase
{
     private User _user;
     public User User
     {
         get { return _user; }
         set
         {
              _user = value;
              OnPropertyChanged("User");
         }
     }
}

Note: in your case the "User" object should probably also be a ViewModel and also raise OnPropertyChanged for the Username property.

Hope this helps.

Anderson Imes
I did but the formatting got messed up. It's right beneath the XAML code. But from the looks of it, it looks good. Thanks!
cmaduro
A: 

The problem was that I was using the SetModel method before the data object was instanced. Moving it like this:



       public ViewModel(IView view)
       {
           View = view;

           User = new User();
           User.Username = "TestUser";

           View.SetModel(this);
       }

solved the problem.

cmaduro
This caused a problem because your ViewModel apparently doesn't implement INotifyPropertyChanged correctly. This should not be an issue. I will update my response with some additional verbiage concerning this.
Anderson Imes