2011-01-21 11 views
3

私はムービーのリストを保持するDatatemplateを持つListViewを持っています。 ObservableColectionにデータバインドされていますが、Movie.Nameを編集するたびに、PropertyChangedEventHandlerで "Name"が呼び出されても "Name"で呼び出されてもListViewは更新されません。ObservableCollectionのデータバインディングMVVM内の<T>

は、私は私の初期化子で私のコレクションに2「ムービー」Sを追加し、これらが正しい表示されます(Klovn映画、撮影)私はそれが選択された映画のテキストを変更し、変更する必要がある[編集]をクリックしますので

"Test"の名前はです。が変更されましたが、変更は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)); 
     } 
    } 
} 

あなたの変更方法が軽減されるもの:


があなたのクラスがどのように見えるか(今、あなたはViewModelにのプロパティ「名前」が存在しない、変更されたことをビューを言っています) To:現在

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://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/432/MVVM-for-Tarded-Folks-Like-Me-or-MVVM-and-What-it-Means-to -Me.aspx彼らはViewModelにINotifyPropertyChangedを入れますか?これは間違っていますか? – Mech0z

+0

いいえ - あなたのケースでは、ViewModel *と* Movieクラスの両方で実装する必要があります。スレッドの中の私の答えを見て、説明を求めてください。 –

+1

viewmodelでも必要ですが、プロパティのプロパティではなく、実際にviewmodelにあるプロパティに対してのみ必要です。 –

2

私はムービー自体がINotifyPropertyChangedを実装する必要があると思います。間違ったオブジェクト(viewmodel)を介して通知しています。

0

、あなたのMainViewModel昇給Name変更するためのNotifyPropertyChangedイベントを抱えています。代わりに、Movieオブジェクトはそのプロパティがバインドされているものなので、Movieインスタンスはそれらのイベントを呼び出す必要があります。

2

ムービークラスにもINotifyPropertyChangedを実装する必要があります。

setMovieNameメソッドで送信している通知は、実際には何も意味しません。単に「プロパティ」名です。 「Foo」と同様に、イベントハンドラが「Foo」と表示されます。

代わりに、Movieオブジェクト自体を更新する必要があります。

おそらく、INotifyPropertyChangedに通知する抽象クラスを作成し、ViewModelとMovieクラスを両方とも実装する必要があるため、それを派生させるのが最適な実装です。

ViewModelからプロパティをバインドすることになります。また、ViewModel内に監視対象オブジェクト(つまりムービー)をバインドすることになります。

関連する問題