【问题标题】:How to bind Instanceproperty to viewmodel, view is not updated如何将Instanceproperty绑定到viewmodel,视图没有更新
【发布时间】:2021-06-16 07:12:19
【问题描述】:

问题:

我的 Viewmodel 创建了一个控制器 mycontroller 的实例,属性 Busy 应传递给 View 并根据控制器状态在 View 中更新,但我的 View 没有得到更新。另一个属性Busy2 根据当前状态更新。 Bindablebase 实现了 I

问题:

为什么 ViewModel 中的属性Busy 没有更新? mycontroller.Busy 属性正在更新,但视图没有更新。

框架和工具:

棱镜 6.3.0

Fody.Property 已更改

查看:

<TextBlock Text="{Binding Path=Busy}"></TextBlock>
<TextBlock Text="{Binding Path=Busy2}"></TextBlock>

视图模型:

public class Controller
    {
        public bool Busy { get; private set; }

        public async void GetValue()
        {
            Busy = true;
            await Task.Delay(5000);
            Busy = false;
        }
    }

    public class MyViewModel : BindableBase
    {
        private readonly Controller _mycontroller;
        public DelegateCommand<string> RunCommand { get; private set; }

        // This property is not updated in the view
        public bool Busy
        {
            get { return _mycontroller.Busy; }
        }

        // Works as aspected
        public bool Busy2 { get; set; }

        public MyViewModel()
        {
            _mycontroller = new Controller();
            RunCommand = new DelegateCommand<string>(Run, Canrun).ObservesProperty((() => _mycontroller.Busy));
        }

        private bool Canrun(string arg)
        {
            return _mycontroller.Busy != true;
        }

        private void Run(string obj)
        {

            Busy2 = true;
            _mycontroller.GetValue();


        }
    }

更新:

我从 Prism 添加了 Bindablebase,因为它实现了 INotifyPropertyChanged,但视图仍然没有更新。 我重构了代码并设置了一个断点来设置{ SetProperty(ref _busy, value); },并且从未达到断点。

我也删除了 Propertychanged.Fody nuget 包。

视图模型:

   public class Controller : BindableBase
    {
        private bool _busy;
        public bool Busy
        {
            get { return _busy; }
            set { SetProperty(ref _busy, value); }
        }

        public Controller()
        {

        }

        public void DoWork1()
        {
            for (var i = 0; i < 10; i++)
            {
                Thread.Sleep(1000);
                _busy = !_busy;
                Debug.WriteLine(_busy.ToString());
            }
        }

        public void DoWork2()
        {
            _busy = !_busy;

        }
    }

    public class MainWindowViewModel : BindableBase
    {
        private Controller mycontroller;
        private string _title = "Prism Unity Application";

        public DelegateCommand RunCommand { get; private set; }

        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        public bool Busy
        {
            get { return mycontroller.Busy; }
        }

        public MainWindowViewModel()
        {
            RunCommand = new DelegateCommand(Execute);
            mycontroller = new Controller();

        }

        private void Execute()
        {
            mycontroller.DoWork1();
        }
    }

查看:

<Window x:Class="PropertytestPrism.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525">
    <StackPanel>
        <Button Command="{Binding RunCommand}" Content="Run"></Button>
        <TextBlock Text="{Binding Busy}"></TextBlock>

    </StackPanel>
</Window>

更新 2

  1. 失败:类 Controller 缺少 INotifypropertychanged

View仍然没有更新,原因是我的Delegatecommand方法,它执行了mycontroller.DoWork1();

问题:

为什么视图没有更新?如果我在 DelegateCommand 方法中执行该方法?

【问题讨论】:

    标签: c# wpf mvvm


    【解决方案1】:

    您应该通过 Controller 类实现 INotifyPropertyChangedController 类中的属性发生了变化,应该通知这种变化:

    public class Controller : INotifyPropertyChanged
    {
        private bool _busy;
    
        public bool Busy 
        {
            get
            {
                return  _busy;
            } 
            private set
            {
                SetField(ref _busy, value, "Busy"); }
            } 
        }
    
        public async void GetValue()
        {
            Busy = true;
            await Task.Delay(5000);
            Busy = false;
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
    
            if (handler != null)
            {
               handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    
        protected bool SetField<T>(ref T field, T value, string propertyName)
        {
            if (EqualityComparer<T>.Default.Equals(field, value))
            {
                return false;
            }
    
            field = value;
            OnPropertyChanged(propertyName);
    
            return true;
        }
    }
    

    【讨论】:

      【解决方案2】:

      试着让你的绑定像这样工作。

      &lt;TextBlock Text="{Binding Busy,Mode=OneWay}"&gt;&lt;/TextBlock&gt;.

      默认情况下绑定是一次性的,因此即使在属性更改通知时它们也不会更新。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-31
        • 2010-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-21
        • 2019-12-19
        相关资源
        最近更新 更多