C# WPF MVVM双向更新
我正在尝试使用设置一个有效的双向更新 以下是相关的代码片段: XAML: 如果你一直读到这里,我已经感谢你了:)不过,通过调用“clkChangeStudent”,我在文本框中没有看到变化。我想这是因为我没有调用StudentViewModel的set方法。我正在做的项目有点复杂,很多事情都发生在课堂上(这里是学生)C# WPF MVVM双向更新,c#,wpf,mvvm,binding,C#,Wpf,Mvvm,Binding,我正在尝试使用设置一个有效的双向更新 以下是相关的代码片段: XAML: 如果你一直读到这里,我已经感谢你了:)不过,通过调用“clkChangeStudent”,我在文本框中没有看到变化。我想这是因为我没有调用StudentViewModel的set方法。我正在做的项目有点复杂,很多事情都发生在课堂上(这里是学生) 如何通过Student类本身中的设置值获取文本框更新?ChangeStudent不调用任何在视图模型中触发属性通知事件的方法,而是更改基础模型。正是这些事件触发视图自我更新 另外,
如何通过Student类本身中的设置值获取文本框更新?ChangeStudent不调用任何在视图模型中触发属性通知事件的方法,而是更改基础模型。正是这些事件触发视图自我更新
另外,您还应该从视图中查看命令绑定,而不是在代码隐藏中使用单击处理程序。这样,您的视图就不需要了解附加的视图模型的任何信息,并且可以是纯粹的表示。ChangeStudent不调用任何在视图模型中触发属性通知事件的方法,而是更改基础模型。正是这些事件触发视图自我更新
另外,您还应该从视图中查看命令绑定,而不是在代码隐藏中使用单击处理程序。这样,您的视图就不需要了解附加的视图模型的任何信息,并且可以是纯粹的表示。首先,您应该使用命令而不是事件 在当前结构中,您必须添加
OnPropertyChanged("StudentLastName");
在StudentViewModel中调用ChangedStudent()方法。
之后,必须将绑定的UpdateSourceTrigger设置为PropertyChanged
Text="{Binding Path=StudentFirstName, UpdateSourceTrigger=PropertyChanged}"
首先,您应该使用命令而不是事件 在当前结构中,您必须添加
OnPropertyChanged("StudentLastName");
在StudentViewModel中调用ChangedStudent()方法。
之后,必须将绑定的UpdateSourceTrigger设置为PropertyChanged
Text="{Binding Path=StudentFirstName, UpdateSourceTrigger=PropertyChanged}"
您的实际代码显然不会通知接口的更改。原因很简单。更改学生名称的方法位于学生模型中,该模型未实现INotifyPropertyChanged 根据一个问题,有两种解决方案可以解决此问题,changeStustudent()方法是否必须与对象模型保持一致,也就是说,您的需求是否允许您将changeStustudent()方法移动到视图模型 如果是,那么,第一个解决方案,只需从模型中删除changeStudent方法并将其移动到视图模型,如下所示:
class StudentViewModel : INotifyPropertyChanged
{
...
public void changeStudent()
{
this.StudentLastName = "McDonald";
}
}
在另一种情况下,第二种解决方案,您必须在模型属性发生更改时引发事件,然后让视图模型支持这些更改。您可以在模型中执行以下操作:
class Student : INotifyPropertyChanged
{
...
private string studentLastName;
public string StudentLastName
{
get
{
return this.studentLastName;
}
set
{
if(this.studentLastname != value)
{
this.studentLastName = value;
this.OnPropertyChanged("StudentLastName");
}
}
}
}
对于视图模型:
class StudentViewModel : INotifyPropertyChanged
{
...
public StudentViewModel(Student model)
{
this._model = model;
this._model.PropertyChanged += (sender, e) =>
{
if(e.PropertyName == "StudentLastName")
{
this.OnPropertyChanged("StudentLastName");
}
};
}
}
这两种解决方案都会奏效。真正重要的是,您必须明白,无论值何时更改,您的代码都需要明确地通知接口。您的实际代码显然不会通知接口的更改。原因很简单。更改学生名称的方法位于学生模型中,该模型未实现INotifyPropertyChanged 根据一个问题,有两种解决方案可以解决此问题,changeStustudent()方法是否必须与对象模型保持一致,也就是说,您的需求是否允许您将changeStustudent()方法移动到视图模型 如果是,那么,第一个解决方案,只需从模型中删除changeStudent方法并将其移动到视图模型,如下所示:
class StudentViewModel : INotifyPropertyChanged
{
...
public void changeStudent()
{
this.StudentLastName = "McDonald";
}
}
在另一种情况下,第二种解决方案,您必须在模型属性发生更改时引发事件,然后让视图模型支持这些更改。您可以在模型中执行以下操作:
class Student : INotifyPropertyChanged
{
...
private string studentLastName;
public string StudentLastName
{
get
{
return this.studentLastName;
}
set
{
if(this.studentLastname != value)
{
this.studentLastName = value;
this.OnPropertyChanged("StudentLastName");
}
}
}
}
对于视图模型:
class StudentViewModel : INotifyPropertyChanged
{
...
public StudentViewModel(Student model)
{
this._model = model;
this._model.PropertyChanged += (sender, e) =>
{
if(e.PropertyName == "StudentLastName")
{
this.OnPropertyChanged("StudentLastName");
}
};
}
}
这两种解决方案都会奏效。非常重要的一点是,您明白,无论值何时更改,代码都需要明确地通知接口。您是在代码隐藏中向集合添加项,而不是使用命令。这不是MVVM,它只是模拟类本身而不是viewmodel中正在发生的事情。这就是我在我的项目中的内容,“学生”保存了关于设备的信息,这些信息在没有任何用户交互的情况下发生了变化,我的目标是创建一个绑定,在用户界面上显示这些信息“实时”。@Robal在这种情况下,您需要有一种方法通知视图模型底层模型已经发生了变化。一种选择是在模型上实现INotifyPropertyChanged,并将其冒泡到视图中,我现在按照Ucodia的回答,向学生本身添加通知,并将其“冒泡”到视图中。这不是我期望的解决方案,但可能会成功。您正在代码隐藏中向集合添加项,而不是使用命令。这不是MVVM,它只是模拟类本身而不是viewmodel中正在发生的事情。这就是我在我的项目中的内容,“学生”保存了关于设备的信息,这些信息在没有任何用户交互的情况下发生了变化,我的目标是创建一个绑定,在用户界面上显示这些信息“实时”。@Robal在这种情况下,您需要有一种方法通知视图模型底层模型已经发生了变化。一种选择是在模型上实现INotifyPropertyChanged,并将其冒泡到视图中,我现在按照Ucodia的回答,向学生本身添加通知,并将其“冒泡”到视图中。这不是我期望的解决方案,但它可能会成功。您不需要在触发器更改状态属性时进行明确说明,这是自动发生的。问题是这个触发器根本没有发生!不需要将UpdateSourceTrigger添加到绑定中,它应该像这样开箱即用:Text=“{binding StudentFirstName}”您不需要明确地将状态属性更改为触发器,这是自动发生的