将依赖属性(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
,视图直接绑定到它。
您需要小心地将 UserControls
的 DataContext
在它们的定义中显式设置为 it can obfuscate what is happening and lead to bindings unexpectedly breaking。如果您想在 UserControl
实例上设置属性,我建议您避免使用它。
有人知道如何同步我在 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
,视图直接绑定到它。
您需要小心地将 UserControls
的 DataContext
在它们的定义中显式设置为 it can obfuscate what is happening and lead to bindings unexpectedly breaking。如果您想在 UserControl
实例上设置属性,我建议您避免使用它。