【问题标题】:Twoway-bind view's DependencyProperty to viewmodel's property?双向绑定视图的 DependencyProperty 到视图模型的属性?
【发布时间】:2013-02-14 11:12:32
【问题描述】:

网络上的多个消息来源告诉我们,在MVVM 中,视图和视图模型之间的通信/同步应该通过依赖属性进行。如果我理解正确的话,应该使用双向绑定将视图的依赖属性绑定到视图模型的属性。现在,以前也有人问过类似的问题,但没有足够的答案。

在我开始分析这个相当复杂的问题之前,这是我的问题:

如何将 自定义 视图的 DependencyProperty 与视图模型的属性同步?

在理想世界中,您只需将其绑定为:

<UserControl x:Class="MyModule.MyView" MyProperty="{Binding MyProperty}">

这不起作用,因为MyProperty 不是UserControl 的成员。嗬!我尝试了不同的方法,但都没有成功。

一种解决方案是定义一个基类UserControlEx,它具有必要的依赖属性,以使上述方法正常工作。然而,这很快变得非常混乱。不够好!

【问题讨论】:

  • 包含MyProperty的对象应该设置为控件的DataContext。
  • 当你使用你的UserControl时,你不会写&lt;myModule:MyView MyProperty="{Binding MyProperty}"&gt;,myModule是一个合适的xmlns声明吗?当然,绑定的来源是以某种方式设置的,或者通过控件的DataContext,或者通过显式设置绑定的Source 或RelativeSource。
  • @Clemens,你的意思是绑定应该发生在视图被实例化的地方?在这种情况下,你如何告诉它使用自己的DataContext 而不是父级的DataContext(实例化的地方)?
  • @l33t 只是为了确保我们谈论的是同一件事。 bound 属性(第一个MyProperty)是UserControl 类MyView 中的依赖属性。绑定源属性(第二个MyProperty,在Binding 声明中)是ViewModel 类中的属性,通常是实现INotifyPropertyChanged 的类中的CLR 属性。
  • @Clemens,是的。这个想法是通过它们的绑定属性在视图和视图模型之间进行通信。许多网站/论坛都提到了这种技术(但从未展示过:P)。

标签: c# wpf mvvm dependency-properties


【解决方案1】:

假设您已经在视图中定义了 DependencyProperty“DepProp”,并希望在 ViewModel 中使用完全相同的值(它实现了 INotifyPropertyChanged,但没有实现 DependencyObject)。您应该能够在 XAML 中执行以下操作:

<UserControl x:Class="MyModule.MyView"
         xmlns:local="clr-namespace:MyModule"
             x:Name="Parent">
    <Grid>
        <Grid.DataContext>
            <local:MyViewModel DepProp="{Binding ElementName=Parent, Path=DepProp}"/>
        </Grid.DataContext>
    ...
    </Grid>
</UserControl>

【讨论】:

    【解决方案2】:

    如果您想在 XAML 中执行此操作,您可以尝试使用样式来实现。

    这是一个例子:

    <UserControl x:Class="MyModule.MyView"
                 xmlns:local="clr-namespace:MyModule">
        <UserControl.Resources>
            <Style TargetType="local:MyView">
                <Setter Property="MyViewProperty" Value="{Binding MyViewModelProperty, Mode=TwoWay}"/>
            </Style>
        </UserControl.Resources>
        <!-- content -->
    </UserControl>
    

    在您的情况下,MyViewProperty 和 MyViewModelProperty 都将命名为 MyProperty,但我使用不同的名称只是为了清楚什么是什么。

    【讨论】:

    • 有趣的想法!也许下次遇到这个问题我会试试看。
    • 谢谢,我正在找这个
    【解决方案3】:

    我使用 Caliburn.Micro 将 ViewModel 与 View 分开。尽管如此,它可能在 MVVM 中以相同的方式工作。我猜 MVVM 也将视图的 DataContext 属性设置为 ViewModel 的实例。

    查看

    // in the class of the view: MyView
    public string ViewModelString // the property which stays in sync with VM's property
    {
        get { return (string)GetValue(ViewModelStringProperty); }
        set
        {
            var oldValue = (string) GetValue(ViewModelStringProperty);
            if (oldValue != value) SetValue(ViewModelStringProperty, value);
        }
    }
    
    public static readonly DependencyProperty ViewModelStringProperty =
        DependencyProperty.Register(
            "ViewModelString",
            typeof(string),
            typeof(MyView),
            new PropertyMetadata(OnStringValueChanged)
            );
    
    private static void OnStringValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        // do some custom stuff, if needed
        // if not, just pass null instead of a delegate
    }    
    
    public MyView()
    {
        InitializeComponent();
        // This is the binding, which binds the property of the VM
        // to your dep. property.
        // My convention is give my property wrapper in the view the same
        // name as the property in the VM has.
        var nameOfPropertyInVm = "ViewModelString"
        var binding = new Binding(nameOfPropertyInVm) { Mode = BindingMode.TwoWay };
        this.SetBinding(SearchStringProperty, binding);
    }
    

    虚拟机

    // in the class of the ViewModel: MyViewModel
    public string ViewModelStringProperty { get; set; }
    

    请注意,这种实现完全缺乏INotifyPropertyChanged 接口的实现。您需要正确更新此代码。

    【讨论】:

    • 调用SetBinding 将与XAML 中定义的任何现有ViewModelString 绑定冲突。只要您不绑定到 XAML 中的 ViewModelString,它就应该可以工作。你知道这是否可以在XAML 中完成吗?
    • 什么意思?仅当您在视图中执行此操作时,XAML 与其代码隐藏之间的绑定才有效:DataContext = this。 MVVM 将 DataContext 属性设置为 ViewModel 的实例。我不知道这可能会导致冲突吗?
    • 我必须回复你。无论如何,以上这些可以在XAML中完成吗?
    • 我知道的唯一方法是我提供的方法。如果有任何 XAML 方式,我认为它不太受欢迎,因为我一直使用上面的方法。在谷歌上搜索这个问题时,我没有发现除此之外的其他结果。
    • 我提到的冲突在这里描述:groups.google.com/forum/?fromgroups=#!topic/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-02
    • 2020-07-20
    • 2013-03-22
    • 2023-03-20
    • 1970-01-01
    • 2022-01-17
    • 2011-05-22
    相关资源
    最近更新 更多