我在WPF中的数据绑定方面遇到了一些问题,所以我一直在尝试弄清楚是怎么回事。但是我遇到了一些我不明白的事情,我希望有人能给我解释一下。下面的代码不是我想要使用的东西,它只是用于测试。
我有一个简单的类"Lamp“,只有一个字符串属性"Name”。我还覆盖了ToString(),以便它返回名称。
在一个"ViewModel“类中,我创建了一个”灯“属性和一个ICommand:
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"/>如果我在命令中创建了一个具有新名称的“灯”的新实例,并调用OnPropertyChanged (仍然在命令中,它在设置器中被注释掉),一切都很好,新值显示在视图中。但如果我不创建新实例,而只是更改当前实例的名称,则视图不会更新。我在命令中设置了一个断点,以查看每次单击按钮时,名称后面都会添加一个"I“,没有什么奇怪的地方。
这里的幕后发生了什么?即使在命令中调用了OnPropertyChanged,是否也需要调用设置器?
正如我所说的,我不想对这段代码做任何具体的解释,只是想要解释一下这种行为。
更新:
我的ViewModelBase看起来像这样:
class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
internal void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}发布于 2019-12-20 06:30:53
您应该使用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;
}
}
}然后,您的代码应该调用OnPropertyChanged
public Lamp Lamp1
{
get { return _lamp1; }
set { SetProperty(ref _lamp1, value; }
}发布于 2019-12-20 07:25:42
在您的代码中,您没有更改属性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 ) );
}
}
}
}属性更改需要在发生更改的地方实现,否则它不会知道它发生了更改。希望这能解释为什么你没有在视图中显示更新。
https://stackoverflow.com/questions/59417576
复制相似问题