将 ViewModel 的属性绑定到 UserControl 的子控件和自身的 DependencyProperty

Posted

技术标签:

【中文标题】将 ViewModel 的属性绑定到 UserControl 的子控件和自身的 DependencyProperty【英文标题】:Bind ViewModel's property to UserControl's child control and itself DependencyProperty 【发布时间】:2021-09-22 05:37:20 【问题描述】:

我想要做的是将我的用户控件的标签绑定到 ViewModel 中的属性值。 但我也想在标签更改时得到通知(并做其他工作,例如提取标签的新值以修改网格宽度等)。

如何做到这一点?

我所做的是:

有一个带有电压属性的视图模型,这是我想要显示的。

UnitVm.cs

    private int m_V;
    public int VoltInVm
    
        get
         return m_V;  
        set
        
            if (m_V != value)
                    
                Set<int>(ref m_V, value, nameof(Volt)); 
            
        
    

和我的用户控件:Unit.cs

public partial class Unit : UserControl

    public static readonly DependencyProperty VoltProperty =
                      DependencyProperty.Register("Volt", typeof(int), typeof(Unit),  
                    new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((Unit)o).OnVoltChanged(o, e)));

    private void OnVoltChanged(double dVolt)
    
            double dWidth;
            if (double.TryParse(strVal, out dWidth))
            
                dWidth = dVolt / 380 * 100;

                if (dWidth > 100)
                    dWidth = 100;

                gridVolt.ColumnDefinitions[0].Width = new GridLength(dWidth, GridUnitType.Star);
                gridVolt.ColumnDefinitions[1].Width = new GridLength(100 - dWidth, GridUnitType.Star);
                       
    
    public int Volt
    
        get  return (int)GetValue(VoltProperty); 
        set
        
            SetValue(VoltProperty, value);
        
    

定义了VoltProperty的DependencyProperty,我想做的工作写在OnVoltChanged里面。

我的意思是当接受来自 ViewModel 的更改时,我可以调用 OnVoltChanged。

在主窗口中使用 Unit 的用户控件:

    <DockPanel DataContext="Binding UnitVm, Source=StaticResource Locator">
        <Viewbox 
            <Label x:Name="lblVolt" Content="Binding VoltInVm" />
        </Viewbox>
    </DockPanel>

lblVolt 绑定到 UnitVm 上下文可以正确更新新的电压值。 但是如何绑定到单位中 Volt 的 DependencyProperty 呢? 这是正确的方法吗?

提前致谢。

【问题讨论】:

不确定您的实际问题是什么。你可以像&lt;local:Unit Volt="Binding VoltInVm"/&gt; 这样使用你的控件。在控件的 XAML 中,您将使用 "Binding Volt, RelativeSource=RelativeSource AncestorType=UserControl" 谢谢。我会试试看。我的问题是要知道视图模型中的绑定属性何时发生变化,因此我可以拦截它并做更多的事情(而不是更新标签的内容,这实际上是自动完成的,不是我自己完成的,我自己也不知道或可定制)。在此示例中添加 DependencyProperty 是为了使用 OnVoltChanged 方法,如果我正确绑定,该方法是视图模型中数据更改的通知 - 这是我的直接问题,我绑定到我的用户控件内的标签已经可以了。跨度> 【参考方案1】:

视图模型属性设置器未正确实现。

它应该如下所示,即使用正确的属性名称nameof(VoltInVm),并且在调用Set 之前可能不检查m_V != value,因为这已经由Set 方法完成。

private int voltInVm;

public int VoltInVm

    get  return voltInVm;  
    set  Set<int>(ref voltInVm, value, nameof(VoltInVm)); 

当你现在绑定 UserControl 的属性时

<local:Unit Volt="Binding VoltInVm"/>

Volt 依赖属性的 PropertyChangedCallback 将在每次 VoltInVm 属性更改其值时被调用。

但是不清楚依赖属性注册中的(o, e) =&gt; ((Unit)o).OnVoltChanged(o, e) 应该是什么。它当然应该是这样的:

(o, e) => ((Unit)o).OnVoltChanged((int)e.NewValue)

并且应该使用int 参数而不是double 声明方法:

private void OnVoltChanged(int volt) ...

或者 - 当然更好 - 在控件和视图模型中将所有电压属性类型更改为 double

【讨论】:

以上是关于将 ViewModel 的属性绑定到 UserControl 的子控件和自身的 DependencyProperty的主要内容,如果未能解决你的问题,请参考以下文章

如何将 WPF DataGrid DataColumns 可见性绑定到 UserControl 的 ViewModel 上的属性?

Kendo UI - 如何使用 Kendo MVVM 将选中的属性(属性)和处理复选框的单击事件绑定到 viewModel

如何将listview项绑定绑定到页面的Viewmodel?

将 StackLayout 绑定到 ViewModel 不起作用

将 ListView 的 SelectedItems 绑定到 ViewModel

将 WPF xaml 绑定到 ViewModel 而不构造它