私はMVVMには比較的新しいので、INotifyPropertyChangedインターフェイスがどのように動作するのか、それを自分のモデルに実装する方法を理解しようとしています。私が取ることに決めたアプローチは、それぞれのビジネスオブジェクトクラスに実装することでした。
このアプローチの問題は、ビューをBaseクラスのプロパティにバインドすると、その基本クラスのPropertyChangedイベントが初期化されることはなく(null)、モデルが変更されたときにそのビューのデータが更新されない。私は以下の例で問題を再現することができました。MVVM INotifyProperty基本クラスとの変更された不具合PropertyChange
私は人基底クラスを持っている:
public class Person : INotifyPropertyChanged
{
#region INotifyProperty
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
public String Name
{
get
{
return _name;
}
set
{
_name = value;
RaisePropertyChanged("Name");
}
}
private String _name;
}
そして、私は私の個人基本クラスから継承するEmployeeクラスを持っている:
3210ここに私のビューモデル:
public class ViewModel : ViewModelBase<ViewModel>
{
private Employee _employee;
public ViewModel()
{
ChangeModelCommand = new RelayCommand(param=>this.ChangeModel() , param=>this.CanChangeModel);
Employee = new Employee()
{
Name = "BOB",EmployeeID = "1234"
};
}
public ICommand ChangeModelCommand { get; set; }
public Employee Employee
{
get
{
return _employee;
}
set
{
this._employee = value;
NotifyPropertyChanged(m=>m.Employee);
}
}
public void ChangeModel()
{
MessageBox.Show("CHANGING MODEL");
this.Employee.Name = "MIKE";
this.Employee.EmployeeID = "5678";
}
public bool CanChangeModel
{
get{ return true;}
}
}
を最後に私のビュー:
<Window.Resources>
<MVVM_NotificationTest:ViewModel x:Key="Model"></MVVM_NotificationTest:ViewModel>
</Window.Resources>
<Grid DataContext="{StaticResource Model}">
<StackPanel>
<Label Content="Employee Name"/>
<TextBox Text="{Binding Path=Employee.Name,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<Label Content="Employee ID"/>
<TextBox Text="{Binding Path=Employee.EmployeeID,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="Change Model" Height="30" Width="100" Margin="5" Command="{Binding Path=ChangeModelCommand}"/>
</StackPanel>
</Grid>
この例では、VMコンストラクタでEmployee VMプロパティを初期化してからEmployeeID(Employeeクラスから)とName(Person Classから)を変更するコマンドがあります。ただし、更新されるビュー内の唯一のUI要素は、EmployeeIDであり、名前ではありません(私はBobがMikeに更新することを期待していました)。
デバッグ中、PropertyChangedイベントがベースクラス(Person)で常にnullであることがわかりました。また、Base Typeイベントとメソッドを使用しているため、Employeeクラスから#INotifyProperty領域全体を削除すると、すべて正常に動作することに気付きました。
私が持っている問題は、すべての現在のモデルクラスが明示的にINotifyPropertyChangedを実装していることです。それらはすべてPropertyChangedイベントを定義し、RaisePropertyChangedメソッドを実装します。これは明らかに私のMVVMアプリケーションでのバインディングに影響を与えます。
最後に、私のViewModelでModelプロパティをラップしてVM INPCメカニズムに依存しないことを明確にしたいと思います。私は、ベース型から継承しているかどうかに応じて、INPC実装を条件付きで削除しなくても、すでにモデルINPC実装を使用したいと考えています。
要約すると、この例で見たように継承がPropertyEventの伝播を壊さないように、私の独立したクラスは自立することができるように、深く階層的なモデルでINPCを実装する最良の方法は何ですか同じように。任意のアイデアや提案は非常に高く評価されます:)
正確には私が考えていたもの:p –
こんにちは@リチャードド、私はそれを試みたが、動作していないようだ。それは、PropertyChanged偶数宣言とRaisePropertyChangedメソッドの両方を基本クラスに移動するときにのみ機能します。 –
これは、クラスが動的に生成されるため、INPC実装が各クラスに大量に追加されています。これが解決策であれば、基本クラスから継承されたときに実装を排除するためのより複雑なロジックが必要になるでしょう:( –