Synchronizing Dependency Properties (View) with Properties (ViewModel)

馋奶兔 提交于 2019-12-10 23:04:10

问题


Does anybody know how I can synchronize my properties, which are in a ViewModel, with my Dependency Properties, which are in the View?

I am trying to make a UserControl, which will then be hosted by a WPF-Window (MainWindow.xaml). The UserControl has an own ViewModel which contains ICommands and properties.

The problem is, that I also have to return certain properties to the MainWindow(.xaml) and also set them.

Currently my classes are looking like that:

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;
}

The dependency property works fine, but the setter method of "Pfad" in the ViewModel never gets called at all.

Thanks in advance!


回答1:


Raising PropertyChanged in the CLR properties of dependency properties is a common mistake. You should not place any code there as it is not used by bindings at all. They exist merely for setting the property once in code or XAML, thus you also will not hit any breakpoints you set there.


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

I take it you want to forward the value to your view-model. This is not going to work as you can only bind the property once. Right now you also bind the property here:

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

You could subscribe to the dependency property changes using the respective meta data when registering it, providing a callback, there you could set the value in the view-model.

The thing is: The view-model is private to the View, there really is no point in doing this synchronization if no-one has access to the data. You probably want the property to be either settable from the outside, treating the UserControl more like a control, discarding the view-model, or you want the view-model to be passed from outside as DataContext, and the view binds directly to it.


You need to be careful with explicitly setting the DataContext of UserControls in their definition, as it can obfuscate what is happening and lead to bindings unexpectedly breaking. If you want to set properties on the UserControl instance i would recommend avoiding it.



来源:https://stackoverflow.com/questions/34375080/synchronizing-dependency-properties-view-with-properties-viewmodel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!