【问题标题】:Binding to dependency property in a ViewModel绑定到 ViewModel 中的依赖属性
【发布时间】:2017-09-07 22:59:14
【问题描述】:

我在 SliderViewModel 中有依赖属性,其中此视图模型实现 DependencyObject 并设置为 BRSliderUserControl 的数据上下文。如何从 AmplitudeOptionsUserControl 绑定到视图模型中的依赖属性。有没有可能这样做。我的猜测是我需要在 BRSliderUserControl 中创建另一个依赖属性,然后将更新值发送到视图模型。这是正确的方法吗?

SliderViewModel.cs

public Class SliderViewModel:DependencyObject
{
    public AnalysisViewType AnalysisTypeValue
            {
                get { return (AnalysisViewType)GetValue(AnalysisTypeDependencyProperty); }
                set { SetValue(AnalysisTypeDependencyProperty, value); }
            }


            public static readonly DependencyProperty AnalysisTypeDependencyProperty =
                DependencyProperty.Register("AnalysisTypeValue", typeof(AnalysisViewType), typeof(SliderViewModel),
                    new PropertyMetadata(AnalysisViewType.Unassigned, OnAnalysisTypeChanged));

            private static void OnAnalysisTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                //Do something here
            }
}

BRSliderUserControl.xaml.cs

  public BRSliderUserControl()
            {
                InitializeComponent();
                SliderViewModel sliderViewModel = new SliderViewModel();
                this.DataContext = sliderViewModel;
            }

现在如何从另一个用户控件绑定到该依赖项属性?

AmplitudeOptionsControl.xaml

//This does not work..

    <lib:BRSliderUserControl
                    Grid.Row="5"
                    Grid.Column="0"
                    Grid.ColumnSpan="3"
                    AnalysisTypeValue="{Binding AmplitudeOptionsVM.AnalysisType,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"
                 />

【问题讨论】:

  • 您的视图模型不应该是依赖对象,也不需要它们。改用 INotifyPropertyChanged,它更轻量级,更合适。
  • 什么是AmplitudeOptionsVMAmplitudeOptionsControl的属性名称?
  • AmplitudeOptionsVM 是类名,AnalysisType 是类内的属性名。
  • 嗯,属性的类型不是属性的名称。如果你想要一个字符串的长度,你不说"foo".int,你说"foo".LengthAmplitudeOptionsControl 是否拥有该虚拟机的副本?如果是DataContext,你要AnalysisTypeValue="{Binding DataContext.AnalysisType,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"

标签: wpf mvvm dependency-properties


【解决方案1】:

将依赖属性移动到UserControl类的代码隐藏中:

public class BRSliderUserControl
{
    public AnalysisViewType AnalysisTypeValue
    {
        get { return (AnalysisViewType)GetValue(AnalysisTypeDependencyProperty); }
        set { SetValue(AnalysisTypeDependencyProperty, value); }
    }

    public static readonly DependencyProperty AnalysisTypeDependencyProperty =
        DependencyProperty.Register("AnalysisTypeValue", typeof(AnalysisViewType), typeof(BRSliderUserControl),
            new PropertyMetadata(AnalysisViewType.Unassigned, OnAnalysisTypeChanged));

    private static void OnAnalysisTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //Do something here
    }

    public BRSliderUserControl()
    {
        InitializeComponent();
        SliderViewModel sliderViewModel = new SliderViewModel();
        this.DataContext = sliderViewModel;
    }
}

向视图模型添加一个普通的 CLR 属性:

public class SliderViewModel : INotifyPropertyChanged
{
    private AnalysisViewType _analysisTypeValue;
    public AnalysisViewType AnalysisTypeValue
    {
        get { return _analysisTypeValue; }
        set { _analysisTypeValue = value; NotifyPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

将视图中的依赖属性绑定到视图模型的源属性:

<lib:BRSliderUserControl
                Grid.Row="5"
                Grid.Column="0"
                Grid.ColumnSpan="3"
                AnalysisTypeValue="{Binding AnalysisTypeValue}" />

【讨论】:

  • NotifyPropertyChanged() 只是一个小修正;应该是 NotifyPropertyChanged("AnalysisTypeValue");
  • @nikhil 方法签名参数上的[CallerMemberName] 属性意味着您可以快捷地传入属性名称
【解决方案2】:

您的视图模型中不需要依赖属性。您的 ViewModel 应实现 INotifyPropertyChanged 接口,并且您的属性应在值更改时引发 NotifyPropertyChanged 事件。周围有很多助手可以让这更容易一些。

您可以根据需要使用 Dependency 属性,但它会使您的视图模型依赖于 WPF,尽管绑定到 Dependency 属性似乎要快得多(参见此处:https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/optimizing-performance-data-binding

您可以在此处查看讨论:INotifyPropertyChanged vs. DependencyProperty in ViewModel

此外,由于您的 DataContext 是 SliderViewModel 类型,它有一个名为 AnalysisTypeValue 的公共属性,因此在您的 XAML 中您应该像这样绑定

... AnalysisTypeValue = {Binding AnalysisTypeValue}

【讨论】:

  • 是的,我知道,但是如何从 AmplitudeOptionsControl 获取分析类型的实际值。问题是我需要从不同的用户控件中获取值并绑定它。 BRSliderUserControl 后面的代码中应该有一个依赖属性,我可以从 AmplitudeOptionsControl 绑定这个值。但每次我需要将此值传播到 ViewModel。
  • 如果您将 View 模型实现为 INPC,则更改后的值在您的 AnalysisTypeValue 设置器中。
猜你喜欢
  • 1970-01-01
  • 2017-07-25
  • 1970-01-01
  • 2019-12-14
  • 1970-01-01
  • 2016-01-22
  • 2023-03-26
  • 2018-05-21
  • 1970-01-01
相关资源
最近更新 更多