C# WPF MVVM双向更新

C# WPF MVVM双向更新,c#,wpf,mvvm,binding,C#,Wpf,Mvvm,Binding,我正在尝试使用设置一个有效的双向更新 以下是相关的代码片段: XAML: 如果你一直读到这里,我已经感谢你了:)不过,通过调用“clkChangeStudent”,我在文本框中没有看到变化。我想这是因为我没有调用StudentViewModel的set方法。我正在做的项目有点复杂,很多事情都发生在课堂上(这里是学生) 如何通过Student类本身中的设置值获取文本框更新?ChangeStudent不调用任何在视图模型中触发属性通知事件的方法,而是更改基础模型。正是这些事件触发视图自我更新 另外,

我正在尝试使用设置一个有效的双向更新

以下是相关的代码片段:

XAML:

如果你一直读到这里,我已经感谢你了:)不过,通过调用“clkChangeStudent”,我在文本框中没有看到变化。我想这是因为我没有调用StudentViewModel的set方法。我正在做的项目有点复杂,很多事情都发生在课堂上(这里是学生)


如何通过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}”您不需要明确地将状态属性更改为触发器,这是自动发生的