将依赖属性(View)与属性(ViewModel)同步

Synchronizing Dependency Properties (View) with Properties (ViewModel)

有人知道如何同步我在 ViewModel 中的属性和我在视图中的依赖属性吗?

我正在尝试创建一个 UserControl,然后它将由 WPF-Window (MainWindow.xaml) 托管。 UserControl 有自己的 ViewModel,其中包含 ICommand 和属性。

问题是,我还必须 return MainWindow(.xaml) 的某些属性并设置它们。

目前我的 类 看起来像这样:

MainWindow.xaml

<TextBox Name="tbInput" VerticalAlignment="Top" HorizontalAlignment="Stretch" Grid.Row="0"></TextBox>
    <local:View x:Name="appEntryView" Pfad="{Binding ElementName=tbInput, Path=Text}" Grid.Row="1" Margin="10"/>

View.xaml

<UserControl x:Class="DependencyProperties.Test"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:DependencyProperties_Intro"
         x:Name="obj"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">

<Grid>
    <TextBlock Text="{Binding ElementName=obj, Path=Pfad}"/>
</Grid>

View.xaml.cs

public partial class View: UserControl, INotifyPropertyChanged
{

    public String Pfad
    {
        get { return (String)GetValue(PfadProperty); }
        set { SetValue(PfadProperty, value); OnNotifyPropertyChanged("Pfad"); }
    }

    // Using a DependencyProperty as the backing store for Path.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty PfadProperty =
        DependencyProperty.Register("Pfad", typeof(String), typeof(GraphSharpTest), new PropertyMetadata(default(string)));

    public View()
    {
        InitializeComponent();
        this.DataContext = new ViewModel();
        var name = "Pfad";
        var binding = new Binding(name) { Mode = BindingMode.TwoWay };
        this.SetBinding(PfadProperty, binding);
    }
}

ViewModel.cs

public class ViewModel: INotifyPropertyChanged
{
    private String m_Pfad;

    public String Pfad
    {
        get { return m_Pfad; }
        set { m_Pfad = value; OnNotifyPropertyChanged("Pfad"); }
    }


    public void OnNotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(info));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

依赖项 属性 工作正常,但是 ViewModel 中 "Pfad" 的 setter 方法根本不会被调用。

提前致谢!

在依赖属性的 CLR 属性中提高 PropertyChanged 是一个常见错误。您应该 将任何代码放在那里,因为绑定根本不使用它。它们的存在仅仅是为了在代码中设置一次 属性 或 XAML,因此您也将 不会 命中您在那里设置的任何断点。


var name = "Pfad";
var binding = new Binding(name) { Mode = BindingMode.TwoWay };
this.SetBinding(PfadProperty, binding);

我认为您想将值转发给您的视图模型。这是行不通的,因为您只能绑定一次 属性。现在您还在这里绑定 属性:

<local:View x:Name="appEntryView" Pfad="{Binding ElementName=tbInput, Path=Text}" Grid.Row="1" Margin="10"/>

您可以在注册时使用相应的元数据订阅依赖项 属性 更改,提供回调,在那里您可以在视图模型中设置值。

问题是:视图模型对 View 是私有的,如果没有人可以访问数据,那么进行这种同步真的没有意义。您可能希望 属性 可以从外部设置,将 UserControl 更像是一个控件,丢弃视图模型,或者您希望视图模型从外部传递为 DataContext,视图直接绑定到它。


您需要小心地将 UserControlsDataContext 在它们的定义中显式设置为 it can obfuscate what is happening and lead to bindings unexpectedly breaking。如果您想在 UserControl 实例上设置属性,我建议您避免使用它。