正在将依赖项属性(视图)与属性(ViewModel)同步

本文关键字:属性 ViewModel 同步 视图 依赖 | 更新日期: 2023-09-27 18:27:22

有人知道我如何将ViewModel中的属性与View中的依赖属性同步吗?

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

问题是,我还必须将某些属性返回到MainWindow(.xaml)并进行设置。

目前我的课程是这样的:

主窗口.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"/>

查看.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>

查看.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;
}

dependency属性运行良好,但ViewModel中的setter方法"Pfad"根本不会被调用。

提前感谢!

正在将依赖项属性(视图)与属性(ViewModel)同步

在依赖属性的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从外部传递,并且视图直接绑定到它。


您需要小心在UserControls的定义中显式设置DataContext,因为这可能会混淆正在发生的事情,并导致绑定意外中断。如果你想在UserControl实例上设置属性,我建议你不要这样做。