【问题标题】:How to notify a bound element oh a value change when value derives from model?当值来自模型时,如何通知绑定元素哦值更改?
【发布时间】:2015-05-28 02:40:55
【问题描述】:

我的视图模型中绑定到以下属性的进度条可见:

public string CalcProgVisibility
{
    get
    {
        return Calculation.CalcProgVisibility;
    }
    set
    {

    }
}

计算是我的模型,它可以改变值。当模型中的值发生变化时,我需要做些什么来确保视图知道这种变化?

编辑:

这也是我的模型中的属性。我正在使用 onpropertychanged 但它没有进入视图。

我正在更改模型中的值,视图绑定到我的视图模型,并且视图模型 si 试图返回从模型中获取的值。我正在更新模型上的值,并且无法将它已将值一直更新到视图的事实推送到视图,我只能让视图模型看到它已更改...

【问题讨论】:

标签: c# wpf mvvm view model


【解决方案1】:

我更新了整个代码。我希望现在很清楚。

定义你的控件 BindingMode = TwoWay

<TextBox Visibility="{Binding Path=CalcProgVisibility, Mode=TwoWay}"...

并在视图模型和模型中的属性设置器上调用 OnPropertyChanged 方法

        //Model
    public class Calculation : INotifyPropertyChanged
    {
        private string _calcProgVisibility;

        public string CalcProgVisibility
        {
            get { return _calcProgVisibility; }
            set
            {
                _calcProgVisibility = value;
                OnPropertyChanged("CalcProgVisibility");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            RaisePropertyChanged(propertyName);
        }

        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler == null) return;

            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    //ViewModel
    public class ViewModel : INotifyPropertyChanged
    {
        public ViewModel(Calculation model)
        {
            this.CalcProgVisibility = model.CalcProgVisibility;
            model.PropertyChanged += (s, e) => UpdateEntity(s as Calculation);
        }

        private void UpdateEntity(Calculation source)
        {
            CalcProgVisibility = source.CalcProgVisibility;
        }      

        private string _calcProgVisibility;

        public string CalcProgVisibility
        {
            get { return _calcProgVisibility; }
            set
            {
                _calcProgVisibility = value;
                OnPropertyChanged("CalcProgVisibility");
            }
        }

         public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            RaisePropertyChanged(propertyName);
        }

        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler == null) return;

            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

【讨论】:

  • 视图绑定到视图模型,但视图模型从模型返回一个变量,并且该变量只在模型中更新。我已经尝试过了,但它不会更新...
  • 此代码只会在“InstallationOrderVisibility”属性更改时触发 UI 更新。就像其他 cmets 所说,您的模型实体也应该实现 INotifyPropertyChanged 以通知视图模型。
  • 这段代码与我所拥有的无关......这段代码返回一个私有布尔值,对于同一个类是本地的,而我所拥有的是从不同类返回一个公共属性。该属性在不同的类中更改。所以不是“return _installOrderVisibility;它应该是“return calc.propertyName;”,其中 calc 指的是另一个类(我的模型)。calc.propertyName 是唯一改变的实际值。
  • 我将帖子中的代码更改为更详细。我希望它有助于解决您的问题。
  • .PropertyChanged 不是在 VM 中被识别的东西。见图片:imgur.com/rgj0COS
【解决方案2】:

您的 Viewmodel 必须实现 INotifyPropertyChanged 接口。要在您的情况下触发它,您的视图模型还必须了解模型对象的更改。所以你的模型对象也可以实现 INotifyPropertyChanged,或者你使用某种形式的观察者模式。

如果您的模型实现 INotifyPropertyChanged,您的视图模型必须手动注册此事件并实现处理程序。这可能反过来触发视图模型的 PropertyChange 事件。

另一种但在我看来丑陋的方式是扫描(每个计时器或后台线程)通过您的 viemodel 并检查自上次扫描以来值是否发生更改,然后触发属性更改事件。

第一个解决方案可能如下所示:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace StackOverflow
{
    [TestClass]
    public class IntegrationTest
    {
        [TestMethod]
        public void NotifyPropertyChangeShouldFireOnViewModelWhenModelChanges()
        {
            //Arrange

            Model model = new Model();
            ViewModel sut = new ViewModel(model);
            bool notifyPropertyChangeOnViewModelWasCalled = false;
            sut.PropertyChanged += (sender, e) => { notifyPropertyChangeOnViewModelWasCalled = true; };

            //Act

            model.CalcValue = 4711;

            //Assert

            Assert.IsTrue(notifyPropertyChangeOnViewModelWasCalled, "NotifyPropertyChange was not fired on ViewModel");
        }
    }


    public class ObjectWithNotifyPropertyChanged : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged([CallerMemberName]string propertyName = "")
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    public class Model : ObjectWithNotifyPropertyChanged
    {
        private double calcValue;
        public double CalcValue
        {
            get
            {
                return calcValue;
            }
            set
            {
                if (calcValue != value)
                {
                    calcValue = value;
                    RaisePropertyChanged();
                }
            }
        }
    }

    public class ViewModel : ObjectWithNotifyPropertyChanged
    {
        public ViewModel(Model model)
        {
            this.model = model;
            model.PropertyChanged += model_PropertyChanged;
        }

        void model_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "CalcValue":
                    RaisePropertyChanged("CalcValue");
                    break;
            }
        }

        private Model model;

        public double CalcValue
        {
            get
            {
                return model.CalcValue;
            }
        }
    }
}

【讨论】:

  • 我的 viewmodel 实现 onpropertychanged 事件什么都不做,因为变量只在模型内部而不是在 viewmodel 内部设置。我在模型上放置了一个 onpropertychanged 事件,但这并没有出现在视图中。
  • 我试图在我的分析器中澄清一下。只是在你的模型中实现 INotifyPropertyChanged 什么都不做。您的视图模型必须为该事件注册一个处理程序,并在必要时将其委托给它自己的 propertychange 事件。
  • 好吧,这是有道理的 :) 但我不知道该怎么做……我该怎么做?谢谢
猜你喜欢
  • 2010-11-23
  • 2014-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多