2009-10-18 11 views
0

J'ai un réel exemple simple qui fonctionne bien sans viewmodel que j'ai un élément classe qui implémente INotifyPropertyChanged:silverlight MVVM viewmodel pour voir la liaison ne fonctionne pas

public class Item : INotifyPropertyChanged 
     { 
      private string _name; 
      private string _desc; 
      public string Name 
      { 
       get 
       { return _name; } 
       set 
       { 
        if (_name == value) 
         return; 
        _name = value; 
        this.OnPropertyChanged(new PropertyChangedEventArgs("Name")); 
       } 
      } 
         } 
      public event PropertyChangedEventHandler PropertyChanged; 

      public Item() 
      { 

      } 

      protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) 
      { 
       if (this.PropertyChanged != null) 
        this.PropertyChanged(this, e); 
      } 

     } 

Cela fonctionne dans un exemple simple où je le code suivant derrière:

public MainPage() 
    { 
     InitializeComponent(); 

     item = new Item() { Name = "john", Description = "this is my name" }; 
     LayoutRoot.DataContext = item; 
    } 

et si j'ai un bouton qui appelle un gestionnaire de commandes dans le code derrière je vois des changements à l'interface utilisateur simple PropertyChanged événement est en train d'être "écouté" à la suite de la liaison Twoway sur ma propriété de texte. le gestionnaire ressemble:

private void Button_Click(object sender, RoutedEventArgs e) 
    { 


     item.Name = "ted"; 
     item.Description = "adddress"; 


    } 

donc bien sûr cela change l'interface (je l'ai dit est réel exemple simple) Maintenant, je vous présente un viewmodel et les modifications apportées au modèle simple ne sont pas reflétés comme il n'y a pas un écouter pour la propriétéchangé.

Je mis la datacontext en vue de la viewmodel, enfait c'est la seule ligne de code dans la vue:

LayoutRoot.DataContext = new MyViewModel(); 

Maintenant, mon ViewModel ressemble:

public class MyViewModel 
    { 
     Item item = null; 
     public ICommand ChangeCommand { get; private set; } 
     public MyViewModel() 
     { 
      item = new Item() { Name = "john", Description = "jjjj" }; 
      ChangeCommand = new DelegateCommand<string>(OnChange); 


     } 
     private void OnChange(string title) 
     { 
      item.Name = "bill"; 

     } 

Notes: J'utilise la commande Patterns and practices pour déclencher l'événement du XAML au Viewmodel et cela fonctionne très bien

Mon gestionnaire modifie à nouveau l'item.name qui entraîne l'appel de l'accesseur set et le this.OnPropertyChanged (new PropertyChangedEventArgs ("Name")); étant appelé, mais personne n'est écoute donc aucun changement n'est effectué. J'essaie de garder cet exemple très simple et certains diront trop simple mais je veux juste savoir pourquoi la liaison ne fonctionne pas. Je peux tirer de la vue à viewmodel mais j'ai besoin de pour pouvoir faire l'inverse. Je me demande quel point je manque.

+0

Je pense que j'ai deviné votre problème correctement, mais la question serait plus claire si vous avez inclus en plus le code de liaison de données XAML. –

Répondre

0

Vous liez une instance de MyViewModel qui n'a aucune propriété exposée publiquement. Essayez de créer et de lier à une propriété publique MyViewModel.Item.

1

fait u semblent être sur la bonne voie comme je l'ai remarqué la même chose et changé le code pour ressembler à:

private Item _item; 

      public ICommand ChangeCommand { get; private set; } 
      public MyViewModel() 
      { 
       myitem = new Item() { Name = "john", Description = "jjjj" }; 
       ChangeCommand = new DelegateCommand<string>(OnChange); 
      } 
      private void OnChange(string title) 
      { 
       _item.Name = "bill"; 
    //   SelectedItem = _item; 

      } 
      public Item myitem 
      { 
       get{return _item;} 
       set 
       { 
        _item = value; 
        RaisePropertyChanged(new PropertyChangedEventArgs("myitem")); 
       } 
      } 

mais mes champs ne sont toujours pas remplis jusqu'à ce que je mets une grille autour de mes textfields et régler le datacontext à travers la grille DataContext = "{Binding MyItem> dans le XAML suivant:

- <UserControl 
    x:Class="BindingStart.MainPage" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 

     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       xmlns:viewmodel="clr-namespace:BindingStart" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 

     xmlns:Commands="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation" 
     mc:Ignorable="d" d:DesignWidth="640" 
    d:DesignHeight="480" 
      > 
     <UserControl.Resources> 
      <viewmodel:MyViewModel x:Key="ViewModel" /> 
     </UserControl.Resources> <Grid x:Name="LayoutRoot" 
    DataContext="{StaticResource 
    ViewModel}"> 
      <StackPanel> 
       <Grid DataContext="{Binding myitem}"> 
       <Grid.RowDefinitions> 
       <RowDefinition Height="22" /> 
       <RowDefinition Height="22" /> 
       <RowDefinition Height="22" /> 
      </Grid.RowDefinitions> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="100" /> 
       <ColumnDefinition Width="300" /> 
       <ColumnDefinition Width="20" /> 
      </Grid.ColumnDefinitions> 

      <TextBlock Grid.Row="0" Grid.Column="0" 
    Foreground="Black">SupplierName</TextBlock> 
      <TextBox x:Name="SName" Grid.Row="0" Grid.Column="1 " 
    IsReadOnly="True"  Text="{Binding 
    Name, Mode=TwoWay}" /> 

maintenant, je aurait pu définir le contexte dans le code, mais je un peu comme la solution XAML Je ne sais pas pourquoi je devais faire. cette étape, mais il semble fonctionner

Questions connexes