MVVM模式下,WPF依赖属性对ViewModel层的数据传递

一.假设在UserControl的设计过程中,你已为控件设置了ViewModel

    <!--ViewModel-->
    <UserControl.DataContext>
        <local:XButtonViewModel x:Name="ViewModel"
                                Text="XButton"
                                TextColor="White"
                                TextHoverColor="Cyan"
                                Background="Transparent"/>
    </UserControl.DataContext>

二.假设在Code-Behind中,你已为控件设置了名为Text的依赖属性

假设使用用户控件XButton时,进行以下赋值操作

<mn:XButton Text="test"/>

(1)正确案例,XButton的文本做出了更新

        public string Text
        {
            get => (string)GetValue(TextProperty);
            set => SetValue(TextProperty, value);
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register(nameof(Text),
                typeof(string), typeof(XButton),
                new PropertyMetadata("XButton", OnTextChanged));

        private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = (XButton)d;
            control.ViewModel.Text = (string)e.NewValue;
        }

(2)错误案例,XButton的文本无法更新

        public string Text
        {
            get => (string)GetValue(TextProperty);
            set
            {
                SetValue(TextProperty, value);
                ViewModel.Text = value;
            }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register(nameof(Text),
                typeof(string), typeof(XButton),
                new PropertyMetadata("XButton"));

三.ChatGpt 给出的解释

  1. 依赖属性的内部机制

    • 依赖属性有自己的一套更新机制和优先级系统。当你在依赖属性的 set 方法中直接调用 ViewModel.Text = value 时,依赖属性的机制可能会覆盖这些更改,特别是如果属性的值来自绑定、样式或其他来源。
    • 依赖属性可能会通过 PropertyChangedCallback 来处理值变化,而在 set 方法中直接更新 ViewModel 不会触发这些回调。
  2. 数据流和同步问题

    • 在 WPF 中,依赖属性的 set 方法和 PropertyChangedCallback 是分开的。直接在 set 方法中更新 ViewModel 不会自动触发 PropertyChangedCallback,也不会通知 WPF 的绑定系统数据已发生变化。
    • 如果 ViewModel.Text 更新了,但 XButton 控件没有正确地同步这些更改,UI 可能不会及时更新。
  3. 绑定和依赖属性的优先级

    • 依赖属性可以从多种来源设置(如样式、绑定等),并且具有优先级系统。如果依赖属性的值被其他机制设置,它可能会覆盖你在 set 方法中设置的值。
    • 如果依赖属性的值通过绑定更新,这种更新机制可能会与 set 方法中的直接更新冲突。

四.总结

MVVM下

【依赖属性 → ViewModel → UI】关系下,不要在set器内直接向 ViewModel传递值,这会被依赖属性的自身机制无效化,使用 PropertyChangedCallback 是解决这个问题的可用方案.

【属性 → ViewModel → UI】关系下,可以在set器内直接向 ViewModel传递值.

不过,向 ViewModel传递值依旧不是推荐的做法,这里可以更换更契合MVVM的处理方式,例如在用户控件中,给某个TextBlock命名 [ x;Name="ActualText" ],它的Text与ViewModel做TwoWay绑定,然后依赖属性变动时,直接改 ActualText.Text,这就避免了Code-Behind与ViewModel的耦合

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值