模型的OnPropertyChanged 不更新UI

问题描述 投票:0回答:1

我在 ViewModel 中使用 DispatchTimer 在模型上引发 OnPropertyChanged,但模型不会在 UI 中更新,除非我引用模型的“TimeSpan”属性。

视图中的 TextBlock 每毫秒更新一次,以显示 TimeSpan 的增加,但 TestUserControl 不会更新。

视图模型

 公共类 TestViewModel:ViewModelBase
    {
        公共DispatcherTimer_timer;

        公共测试视图模型()
        {
            Test1 = new TestObject();
            Test1.Name = "测试名称";
            Test1.DateTime = DateTime.Now;

            _timer = new DispatcherTimer(DispatcherPriority.Render);
            _timer.Interval = TimeSpan.FromMilliseconds(1);
            _timer.Tick += (发送者, args) =>
            {
                OnPropertyChanged(nameof(测试));
            };
            _timer.Start();
        }

        私有测试对象测试1;
        公共测试对象测试1
        {
           得到
           {
               返回测试1;
           }
               放
           {
               测试1=值;
               OnPropertyChanged(nameof(Test1));
           }
        }
    }

型号

 公共类测试对象
    {
        公共字符串名称{获取;放; }
        公共日期时间日期时间{获取;放; }
        公共 TimeSpan TimeSpan => DateTime.Now - DateTime;
    }

查看

    <StackPanel>
        <userControls:TestUserControl DataContext="{Binding Test1}"/>
        <TextBlock Text="{Binding Test1.TimeSpan}"/> //updating on UI
    </StackPanel>

测试用户控件

    <StackPanel>
        <TextBlock Text="{Binding Name}"/> //shows initial value
        <TextBlock Text="{Binding TimeSpan}"/> //shows initial value and does not update
    <StackPanel>
c# wpf mvvm
1个回答
0
投票

也许可以从在您的

INotifyPropertyChanged
模型中实现
TestObject
开始。然后,当我实际运行你的代码时,似乎这可能就是你想要的?

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            DataContext = new TestViewModel();
            InitializeComponent();
        }
    }
    public class TestViewModel : ViewModelBase
    {
        public DispatcherTimer _timer;

        public TestViewModel()
        {
            Test1 = new TestObject();
            Test1.Name = "TestName";

            _timer = new DispatcherTimer(DispatcherPriority.Render);
            _timer.Interval = TimeSpan.FromSeconds(1);
            _timer.Tick += (sender, args) =>
            {
                Test1.TimeSpan = DateTime.Now - Test1.DateTimeInit;
            };
            _timer.Start();
        }

        private TestObject test1;
        public TestObject Test1
        {
            get
            {
                return test1;
            }
            set
            {
                test1 = value;
                OnPropertyChanged(nameof(Test1));
            }
        }
    }
    public class TestObject : INotifyPropertyChanged
    {
        public string Name
        {
            get => _name;
            set
            {
                if (!Equals(_name, value))
                {
                    _name = value;
                    OnPropertyChanged();
                }
            }
        }
        string _name = string.Empty;

        public DateTime DateTimeInit { get; } = DateTime.Now;
        
        public TimeSpan TimeSpan
        {
            get => _timeSpan;
            set
            {
                if (!Equals(_timeSpan, value))
                {
                    _timeSpan = value;
                    OnPropertyChanged();
                }
            }
        }
        TimeSpan _timeSpan = default;

        private void OnPropertyChanged([CallerMemberName] string? propertyName = null) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        public event PropertyChangedEventHandler? PropertyChanged;
    }
    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.