2011-01-21 43 views
3

我有一個ListView和Datatemplate,它包含一個Movies列表。它被數據綁定到一個ObservableCollection,但是每當我編輯Movie.Name它都不會更新ListView,即使在我的PropertyChangedEventHandler中調用「Name」時使用「Name」調用。Datavinding ObservableCollection <T> MVVM

我加2「電影」 s到我的收藏我的初始化和這些顯示正確(Klovn電影,服用)

所以,當我點擊編輯,應該更改所選電影的文字和改變它的名稱爲「測試」,並且被更改爲,但該更改未在ListView中顯示,但如果使用foreach輸出Collection,則Name爲Test。

View.xaml

<Window x:Class="MovieDB3.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <DockPanel> 
     <Menu DockPanel.Dock="Top"> 
      <MenuItem Header="File"> 
       <MenuItem Header="Edit" Click="MenuEditClick"/> 
      </MenuItem> 
     </Menu> 
     <Grid DockPanel.Dock="Top"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition/> 
       <ColumnDefinition/> 
      </Grid.ColumnDefinitions> 
      <Grid.RowDefinitions> 
       <RowDefinition/> 
      </Grid.RowDefinitions> 
      <ListView VerticalAlignment="Stretch" Name="ListViewMovies" ItemsSource="{Binding Path=Collection}" IsSynchronizedWithCurrentItem="True" > 
       <ListView.ItemTemplate> 
        <DataTemplate> 
         <WrapPanel> 
          <TextBlock Text="{Binding Path=Name}"/> 
         </WrapPanel> 
        </DataTemplate> 
       </ListView.ItemTemplate> 
      </ListView> 
     </Grid> 
    </DockPanel> 
</Window> 

View.cs

using System; 
using System.Windows; 
using MovieDB3.Models; 
using MovieDB3.ViewModels; 

namespace MovieDB3 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     private MainViewModel MVM; 
     public MainWindow() 
     { 
      InitializeComponent(); 
      MVM = new MainViewModel(); 
      DataContext = MVM; 
     } 

     private void MenuEditClick(object sender, RoutedEventArgs e) 
     { 
      MVM.setMovieName((Movie)ListViewMovies.SelectedItem, "test"); 
     } 
    } 
} 

視圖模型

using System; 
using System.ComponentModel; 
using MovieDB3.Models; 
using System.Collections.ObjectModel; 

namespace MovieDB3.ViewModels 
{ 
    class MainViewModel : INotifyPropertyChanged 
    { 
     public ObservableCollection<Movie> Collection {get; set;} 

     public MainViewModel() 
     { 
      Collection = new ObservableCollection<Movie>(); 

      //Test kode 
      Movie movie = new Movie(); 
      movie.Name = "Klovn The Movie"; 
      Collection.Add(movie); 
      movie = new Movie(); 
      movie.Name = "Taken"; 
      Collection.Add(movie); 
     } 

     public void setMovieName(Movie movie, string newName) 
     { 
      //movie.Name = newName; 
      Console.WriteLine("CurrentName: " + movie.Name); 
      int i = Collection.IndexOf(movie); 
      Collection[i].Name = newName; 
      Console.WriteLine("NewName: " + movie.Name); 
      NotifyPropertyChanged("Name"); 
     } 

     public void setMovieName(string currentName, string newName) 
     { 
      foreach (Movie movie in Collection) 
      { 
       if (movie.Name.Equals(currentName)) 
       { 
        movie.Name = newName; 
        NotifyPropertyChanged("Name"); 
        return; 
       } 
      } 
     } 

     //public string MovieName 
     //{ 
     // set 
     // { 

     //  NotifyPropertyChanged("MovieName"); 
     // } 
     //} 

     public event PropertyChangedEventHandler PropertyChanged; 

     private void NotifyPropertyChanged(String info) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(info)); 
      } 
     } 
    } 
} 

Movie.cs

using System; 

namespace MovieDB3.Models 
{ 
    class Movie 
    { 
     public string Name { get; set; } 
     public int Id { get; set; } 
     public double Rating { get; set; } 
     public DateTime Release { get; set; } 
     public TimeSpan Runtime { get; set; } 
     public String Trailer { get; set; } 
    } 
} 

回答

8

INotifyPropertyChanged需要在Movie類中實現,也避免手動引發事件。 (現在你告訴認爲,視圖模型的「名稱」屬性改變,這不存在)


類可能是什麼樣子:

public class Movie : INotifyPropertyChanged 
{ 
    private string _name = String.Empty; 
    public string Name 
    { 
     get { return _name; } 
     set 
     { 
      if (_name != value) 
      { 
       _name = value; 
       NotifyPropertyChanged("Name"); 
      } 
     } 
    } 

    //...All the other properties (the same way)... 

    public event PropertyChangedEventHandler PropertyChanged; 

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

你的改變方法降低於:

public void setMovieName(Movie movie, string newName) 
    { 
     Console.WriteLine("CurrentName: " + movie.Name); 
     movie.Name = newName; //The notification is now raised automatically in the setter of the property in the movie class 
     Console.WriteLine("NewName: " + movie.Name); 
    } 
+0

但是在http://journals.hjtcentral.com/Home/tabid/428/EntryId/432/MVVM-for-Tarded-Folks-Like-Me-or-MVVM-and-What-it-Means-to -Me.aspx他們把INotifyPropertyChanged放在ViewModel中?這是錯的嗎? – Mech0z 2011-01-21 19:11:05

2

我認爲電影本身需要實現INotifyPropertyChanged。您正在通過錯誤的對象(視圖模型)進行通知。

0

目前,你有你的MainViewModel加薪的NotifyPropertyChanged事件Name變化。相反,您的Movie實例應該引發這些事件,因爲您的Movie對象是該屬性綁定的對象。

2

您還需要在Movie類上實現INotifyPropertyChanged。

您在setMovieName方法中發送的通知並不意味着什麼 - 它只是一個「屬性」名稱。它也可以是「Foo」,而你的事件處理程序會說「Foo」。

相反,您需要更新對象本身的Movie

可能最好的實現是爲你創建一個抽象類來通知INotifyPropertyChanged,然後從它派生你的ViewModel和你的Movie類,因爲兩者都應該實現它。

您將綁定來自ViewModel的屬性,並且您還將綁定該ViewModel中的可觀察對象(即Movie)。

相關問題