首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果不创建绑定对象的新实例,则OnPropertyChange不会更新绑定

问如果不创建绑定对象的新实例,则OnPropertyChange不会更新绑定
EN

Stack Overflow用户
提问于 2019-12-20 06:19:08
回答 2查看 133关注 0票数 0

我在WPF中的数据绑定方面遇到了一些问题,所以我一直在尝试弄清楚是怎么回事。但是我遇到了一些我不明白的事情,我希望有人能给我解释一下。下面的代码不是我想要使用的东西,它只是用于测试。

我有一个简单的类"Lamp“,只有一个字符串属性"Name”。我还覆盖了ToString(),以便它返回名称。

在一个"ViewModel“类中,我创建了一个”灯“属性和一个ICommand:

代码语言:javascript
复制
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的标签:

代码语言:javascript
复制
        <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看起来像这样:

代码语言:javascript
复制
class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        internal void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
EN

回答 2

Stack Overflow用户

发布于 2019-12-20 06:30:53

您应该使用INotifyPropertyChanged并将代码添加到ViewModelBase类中,以更新视图上的任何对象。

代码语言:javascript
复制
{
    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

代码语言:javascript
复制
public Lamp Lamp1
        {
            get { return _lamp1; }
            set { SetProperty(ref _lamp1, value; }
        }
票数 0
EN

Stack Overflow用户

发布于 2019-12-20 07:25:42

在您的代码中,您没有更改属性Lamp1。您正在更改lamp类Name中的属性。如果在lamp类中使用Name字段实现INotifyPropertyChanged,它将会更新。使用当前代码,如果您将Lamp1更改为具有不同名称的Lamp的新实例,那么它将记录更改,因为您正在更改Lamp1字段。

代码语言:javascript
复制
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 ) );
            }
        }
    }
}

属性更改需要在发生更改的地方实现,否则它不会知道它发生了更改。希望这能解释为什么你没有在视图中显示更新。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59417576

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档