C# 如果不创建绑定对象的新实例,OnPropertyChange不会更新绑定
我在WPF中的数据绑定方面遇到了一些问题,所以我一直在尝试弄清楚到底发生了什么。但是我遇到了一些我不明白的事情,我希望有人能给我解释一下。下面的代码不是我试图使用的任何东西,它只是用于测试 我有一个简单的类“Lamp”,只有一个字符串属性“Name”。我还重写ToString(),以便它返回名称 在“ViewModel”类中,我创建了一个“Lamp”属性和一个ICommand:C# 如果不创建绑定对象的新实例,OnPropertyChange不会更新绑定,c#,wpf,data-binding,C#,Wpf,Data Binding,我在WPF中的数据绑定方面遇到了一些问题,所以我一直在尝试弄清楚到底发生了什么。但是我遇到了一些我不明白的事情,我希望有人能给我解释一下。下面的代码不是我试图使用的任何东西,它只是用于测试 我有一个简单的类“Lamp”,只有一个字符串属性“Name”。我还重写ToString(),以便它返回名称 在“ViewModel”类中,我创建了一个“Lamp”属性和一个ICommand: class ViewModel : ViewModelBase { private Lamp _lam
class ViewModel : ViewModelBase
{
private Lamp _lamp1;
public Lamp Lamp1
{
get { return _lamp1; }
set { _lamp1 = value; }// OnPropertyChanged("Lamp1"); }
}
public ICommand Lamp_click { get { return new RelayCommand(param => LampClickExecute(param)); } }
public ViewModel()
{
Lamp1 = new Lamp() { Name = "Test" };
}
private void LampClickExecute(object param)
{
var name = Lamp1.Name + "I";
//HERE IS THE QUESTION!
//Lamp1 = new Lamp() { Name = name };
Lamp1.Name = name;
OnPropertyChanged("Lamp1");
}
}
在视图中,我只有一个绑定到命令的按钮和一个绑定到Lamp1的标签:
<Button x:Name="btn_lamp" Content="Button" HorizontalAlignment="Left" Margin="859,27,0,0" VerticalAlignment="Top" Height="29" Command="{Binding Path= Lamp_click}" CommandParameter="{Binding Path=Lamp1 }"/>
<Label Content= "{Binding Lamp1}" HorizontalAlignment="Left" Margin="797,56,0,0" VerticalAlignment="Top"/>
您应该使用INotifyPropertyChanged并将代码添加到ViewModelBase类中,以更新视图上的任何对象
{
public class ViewModelBase: INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
protected bool SetProperty<T>(ref T backingStore, T value,
[CallerMemberName]string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
}
}
在代码中,您没有更改属性
Lamp1
。您正在更改lamp类Name
中的属性。如果在lamp类中使用Name
字段实现INotifyPropertyChanged
,它将更新。对于当前代码,如果您将Lamp1
更改为具有不同名称的Lamp
的新实例,则它将记录更改,因为您正在更改Lamp1
字段
public class Lamp : NotifyChange { //NotifyChange is the INotifyPropertyChanged implementation in a base class
private _Name;
public Name{
get{ return _Name; }
set{
if( _Name != value ) {
_Name = value;
OnPropertyChanged( nameof( Name ) );
}
}
}
}
属性更改需要在更改发生的位置执行,否则它将不知道其已更改。希望这能解释为什么您没有在视图中显示更新。除了Jorge Guerrero的答案之外,您可以尝试在XAML中的
Lamp1
绑定中添加以下内容,UpdateSourceTrigger=PropertyChanged
我的ViewModelBase比这简单,但它实现了INotifyPropertyChanged,正如我所说,如果我将新实例设置为Lamp1,则视图将更新。所以我想我说对了?在您的版本中,我看到了与旧值的比较,但我没有类似的内容,而且,如果不创建新实例,该值不会更新。谢谢!这意味着通过绑定绑定到PropertyChangedEventHandler的方法在何时更新视图上实现了一些限制?它不是每次调用时都强制更新吗?这里有人知道为什么吗?@elg不,它总是实现更新它只是取决于你在哪里实现propertychangedventhandler
,就像我在回答中说的那样。如果您正在更改名称,他们将在那里实现它,或者如果您正在创建lamp的新实例,请在那里实现它。
public Lamp Lamp1
{
get { return _lamp1; }
set { SetProperty(ref _lamp1, value; }
}
public class Lamp : NotifyChange { //NotifyChange is the INotifyPropertyChanged implementation in a base class
private _Name;
public Name{
get{ return _Name; }
set{
if( _Name != value ) {
_Name = value;
OnPropertyChanged( nameof( Name ) );
}
}
}
}