在同一个Setter中调用多个OnPropertyChanged(或者有其他简单的方法)
本文关键字:其他 或者 简单 方法 OnPropertyChanged Setter 同一个 调用 | 更新日期: 2023-09-27 17:54:08
我尽量使我的问题简单扼要。
目前,如果我有一个更新底层Model
数据的属性,因此它需要通知其他一些属性源已经更改,我这样做:
public Data.MeetingInfo.Meeting Meeting
{
get { return _Meeting; }
set
{
if(value != null)
{
_Meeting = value;
if (_Meeting.IsDirty)
{
_Model.Serialize();
_Meeting.MarkClean();
OnPropertyChanged("Meeting");
OnPropertyChanged("BibleReadingMain");
OnPropertyChanged("BibleReadingClass1");
OnPropertyChanged("BibleReadingClass2");
}
}
}
}
private Data.MeetingInfo.Meeting _Meeting;
可以看到,我添加了几个不同的OnPropertyChanged
方法调用。这样做可以接受吗?或者,Model
的特定性质会告诉View
它的某些来源发生了变化吗?
我读过关于在Model
类中实现相同的OnPropertyChanged
功能的文章。因此,XAML将拾取它。但是我认为MWWV
的这两个部分我们不应该知道彼此。
问题是,其他3是在禁用控件,但他们可以从窗口上的两个地方更新。所以我认为我不能有两个更新源触发器,对吧?
谢谢。
第二次解释:
ObservableCollection of Meeting
对象。Bound
to a ComboBox
:
<ComboBox x:Name="comboMeetingWeek" ItemsSource="{Binding Meetings}"
SelectedItem="{Binding Meeting, UpdateSourceTrigger=PropertyChanged}" />
Meeting
对象包含几个属性。我们用这些属性绑定窗口上的控件。例子:
<ComboBox x:Name="comboNotes" IsEditable="True"
DataContext="{Binding Meeting}"
Text="{Binding Note, UpdateSourceTrigger=LostFocus}"
ItemsSource="{StaticResource Notes}"/>
我对大多数控件都这样做。因此,视图模型中的Meeting属性保持最新,然后当您选择不同的会议时,它将其提交到模型数据并显示新会议(如前所述)。
但是,在窗口的某些地方,我有一些禁用的文本框。这些属性与嵌套在Meeting对象中的属性相关联。例如:
<TextBox x:Name="textBibleReadingMain" Grid.Column="0" Margin="2" IsEnabled="False"
DataContext="{Binding TFGW.BibleReadingItem.Main}"
Text="{Binding DataContext.BibleReadingMain, ElementName=oclmEditor, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"/>
父TabItem
已经将其DataContext
设置为{Binding Meeting}
。我们需要在文本框中显示的内容是:
Meeting (current context).TFGW.BibleReadingItem.Main.Name
这就是为什么我必须做我做过的事。对于上面的文本框,这是我想允许发生的:
它应该显示
Meeting.TFGW.BibleReadingItem.Main.Name
的内容(会议已经是一个绑定属性)当您从日期组合中选择不同的会议时,此文本框应更新。
如果用户从
DataGrid
和中选择一个名称,ActiveAstudentAssignmentType
组合被设置为StudentAssignmentType::BibleReadingMain
,那么我也想更新文本框。
我想我感到困惑的是当我应该从INotifyPropertyChanged
派生我的类。我的模型数据是会议对象和它自己的数据。所有这些都应该从INotifyPropertyChanged继承和提高OnPropertyChanged?目前,我没有在任何地方实施。我说谎,我实现它的唯一地方是视图模型本身:
public class OCLMEditorViewModel : INotifyPropertyChanged
所以这就是为什么我必须这样做。
清晰吗?
基于所有的评论和进一步的研究....
其中一个答案是:
- 视图模型被创建并包装模型
- Viewmodel 订阅模型的PropertyChanged事件
- Viewmodel被设置为view的DataContext,属性被绑定等等
- 视图触发视图模型
操作- 视图模型调用模型上的方法
- 模型自我更新
- Viewmodel处理模型的PropertyChanged并在响应
中引发自己的PropertyChanged- 视图反映其绑定的变化,关闭反馈循环
我也读了一点(这让我有些困惑),它说:
如果底层数据存储中的数据发生了变化,Model 会通知 ViewModel。
所以,我做的第一件事是改变我的Meeting
对象从INotifyPropertyChanged
派生。此外,我还添加了新的属性,用于访问Meeting模型中的更深层数据。示例(精简):
public class Meeting : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
#region Bible Reading Name Properties
[XmlIgnore]
public string BibleReadingMainName
{
get { return _TFGW.BibleReadingItem.Main.Name; }
set
{
_TFGW.BibleReadingItem.Main.Name = value;
OnPropertyChanged("BibleReadingMainName");
}
}
[XmlIgnore]
public string BibleReadingClass1Name
{
get { return _TFGW.BibleReadingItem.Class1.Name; }
set
{
_TFGW.BibleReadingItem.Class1.Name = value;
OnPropertyChanged("BibleReadingClass1Name");
}
}
[XmlIgnore]
public string BibleReadingClass2Name
{
get { return _TFGW.BibleReadingItem.Class2.Name; }
set
{
_TFGW.BibleReadingItem.Class2.Name = value;
OnPropertyChanged("BibleReadingClass2Name");
}
}
#endregion
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
在我的ViewModel我将其设置为PropertyChanged
的侦听器:
_Meeting.PropertyChanged += Meeting_PropertyChanged;
在这个时间点,处理程序只是传递被更改的属性:
private void Meeting_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(e.PropertyName);
}
在我的XAML中,我调整了TextBox
以使用新属性,并删除了DataContext引用。现在我有:
<TextBox x:Name="textBibleReadingMain" Grid.Column="0" Margin="2" IsEnabled="False"
Text="{Binding BibleReadingMainName, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
在右边,我有DataGrid
,当我们点击一行,SelectedStudentItem
被更新,我们现在可以做:
private Student _SelectedStudentItem;
public Student SelectedStudentItem
{
get
{
return _SelectedStudentItem;
}
set
{
// We need to remove this item from the previous student history
if (_SelectedStudentItem != null)
_SelectedStudentItem.History.Remove(Meeting.DateMeeting);
_SelectedStudentItem = value;
if (_SelectedStudentItem == null)
return;
_EditStudentButtonClickCommand.RaiseCanExecuteChanged();
_DeleteStudentButtonClickCommand.RaiseCanExecuteChanged();
OnPropertyChanged("SelectedStudentItem");
if (ActiveStudentAssignmentType == StudentAssignmentType.BibleReadingMain)
_Meeting.BibleReadingMainName = _SelectedStudentItem.Name;
else if (ActiveStudentAssignmentType == StudentAssignmentType.BibleReadingClass1)
_Meeting.BibleReadingClass1Name = _SelectedStudentItem.Name;
else if (ActiveStudentAssignmentType == StudentAssignmentType.BibleReadingClass2)
_Meeting.BibleReadingClass2Name = _SelectedStudentItem.Name;
}
基于当前ActiveStudentAssignmentType
的值,我们可以直接更新source属性。因此,TextBox
将自动知道它,因为PropertyChange
侦听器。
public Data.MeetingInfo.Meeting Meeting
{
get { return _Meeting; }
set
{
// Has the existing meeting object changed at all?
if(_Meeting != null && _Meeting.IsDirty)
{
// Yes, so save it
_Model.Serialize();
_Meeting.MarkClean();
}
// Now we can update to new value
if (value != null)
{
_Meeting = value;
OnPropertyChanged("Meeting");
}
}
}
private Data.MeetingInfo.Meeting _Meeting;
所有那些额外的OnPropertyChanged调用现在已经过时了!
我缺少的是实现通知从模型到ViewModel。然后是ViewModel通知View