【问题标题】:Property change is not propagated to binding target (UWP)属性更改不会传播到绑定目​​标 (UWP)
【发布时间】:2019-02-17 22:31:30
【问题描述】:

我有一个 ViewModel 和一个类。它们看起来像这样:

//viewmodel
public class MyViewModel : ViewModelBase {

    private MyClass myClass;
    public MyClass MyClass{
        get{
            return myClass;
        }
        set{
            this.myClass = value;
            base.OnPropertyChanged();
        }
    }

    private string testString;
    public string TestString{
                get{
            return testString;
        }
        set{
            this.testString = value;
            base.OnPropertyChanged();
        }
    }

    public MyViewModel(){
        this.MyClass = new MyClass();
        this.TestString = "blah, blah, blah"
    }}



//class
    public class MyClass : ViewModelBase{
    private string  myString;
    public string MyString{
        get {
        return myString
        }
        set{
            this.myString = value;
            base.OnPropertyChanged();
        }
    }

    public MyClass (){
        this.MyString = "25";   }}

基类 - ViewModelBase 实现 INotifyChange 并包含 OnPropertyChanged 处理程序逻辑。 我有一个 UserControl,我希望像这样绑定 MyClass 中的值:

  <TextBlock Text="{x:Bind  Path=MyViewModel.MyClass.MyString, Mode=TwoWay}"></TextBlock>

但是这不起作用。值在初始化中正确绑定,但 MyViewModel.MyClass.MyString 中的任何更改都不会反映在 texblock 中,文本保持不变。引发了 OnPropertyChange,ViewModelBase 中的断点被 MyString 值更改,但它以某种方式没有传播到 texblock。 绑定 MyClass 中的简单值就像魅力一样,当属性更改时,此文本块会更新:

  <TextBlock Text="{x:Bind  Path=MyViewModel.TestString, Mode=TwoWay}"></TextBlock>

我错过了什么?为什么绑定到“MyViewModel.MyClass.MyString”的文本块没有更新?

【问题讨论】:

    标签: xaml binding uwp inotifypropertychanged


    【解决方案1】:

    我已经测试了您提供的代码,认为它没有任何问题。但是,问题可能出在页面的代码隐藏处。万一,您不是将其用作属性声明吗?

    public MyViewModel MyViewModel => new MyViewModel();
    

    因为在这种情况下,对MyViewModel 属性的每次访问都会评估为MyViewModel 类的新实例。在此配置中,您可以正确更改属性,但 UI 不会注意到,因为您将在新实例上更新属性。如果您改为使用

    public MyViewModel MyViewModel { get; } = new MyViewModel();
    

    您将获得在创建页面时只创建一个实例的正确行为。

    我有以下代码:

    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();            
        }
    
        public MyViewModel MyViewModel { get; } = new MyViewModel();
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MyViewModel.MyClass.MyString = "test";
        }
    }
    

    还有我的简单ViewModelBase

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

    【讨论】:

    • 感谢您的回答。我没有通过 lambda 运算符设置 MyViewModel,但是我正在从 DI 容器中解析它,例如“this”。 MyViewModel = DIManager.Instance.DIContainer.Resolve();“。 MyViewModel 在 DI 中注册为单例,所以我假设实例没有问题。 MyViewModel.TestString 也运行良好。问题只是 MyViewModel.MyClass 中的属性。
    • 顺便说一句,我的 ViewModelBase 和你的一样,我只是在调度程序中运行它,因为它是从后台威胁更新 UI 的问题。我不认为这是一个问题,因为正如我所说 MyViewModel.TestString 有效。如果您有任何想法,我们将不胜感激。
    • 这很奇怪,真的。当您用新实例完全替换 MyClass 时会发生什么?喜欢MyViewModel.MyClass = new MyClass() { MyString = "something else" }
    • 我试过了,不幸的是行为完全一样。我已经找到了解决方法,但我对此并不特别满意。在 UserControl 中,我创建了一个新的字符串属性“newString”。我订阅了事件 MyViewModel.MyClass.PropertyChanged,在处理程序中我有“this.newString = this.MyViewModel.MyClass.MyString”,在 xaml 中我绑定到“newString”。这确实有效,但它不是非常整洁和干净的解决方案。希望这只是暂时的。
    • 这很奇怪,我的电脑上有完全相同的代码,它确实有效。如果有机会,您能否创建一个新的解决方案,在那里创建相同的代码并将其发送给我或分享到 GitHub?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-08
    • 1970-01-01
    • 2019-09-29
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多