C# 如何从继承的用户控件访问viewModel依赖项属性?
我在一个演示WPF项目中苦苦挣扎。我必须认识到,我有许多限制,使代码复杂化 核心元素是从UserControl继承的控件。我希望它的代码尽可能的简单。另外,我希望它的XAML在ControlTemplate中。它的C#代码应该在一个专用的ViewModel中(这个例子适用于一个大型项目,拥有一个专用的ViewModel可以通过对所有ViewModel进行分组来提供帮助。但无论如何,说它是强制性的)。 最后,但并非最不重要的是,我想将此控件的2个属性绑定到外部属性 这是我的MainWindow.xaml文件:C# 如何从继承的用户控件访问viewModel依赖项属性?,c#,wpf,mvvm,dependency-properties,C#,Wpf,Mvvm,Dependency Properties,我在一个演示WPF项目中苦苦挣扎。我必须认识到,我有许多限制,使代码复杂化 核心元素是从UserControl继承的控件。我希望它的代码尽可能的简单。另外,我希望它的XAML在ControlTemplate中。它的C#代码应该在一个专用的ViewModel中(这个例子适用于一个大型项目,拥有一个专用的ViewModel可以通过对所有ViewModel进行分组来提供帮助。但无论如何,说它是强制性的)。 最后,但并非最不重要的是,我想将此控件的2个属性绑定到外部属性 这是我的MainWindow.x
<Window x:Class="ViewModel_defined_in_ControlTemplate.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ViewModel_defined_in_ControlTemplate"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<StackPanel>
<local:MyUserControl Template="{StaticResource TextBoxTemplate}"
NomPersonne="sg"/>
<Button Content="Click me!" Command="{Binding ElementName=MyViewModel,Path=ChangeTextBoxContent}" Width="100" HorizontalAlignment="Left"/>
</StackPanel>
</Grid>
</Window>
现在可以从MyUserCOntrol的XAML访问它,但我不知道如何访问它,以便让按钮的命令更改属性:
namespace ViewModel_defined_in_ControlTemplate
{
public class MyViewModel : ViewModelBase
{
public RelayCommand ChangeTextBoxContent = new RelayCommand(() =>
{
//...
}, () => true);
}
}
我更希望在viewmodel中具有dependency属性,但在这种情况下,如何在主窗口中访问MyUserControl的XAML中的
谢谢。您应该向视图模型添加源属性,将UserControl
的目标属性绑定到此属性,并更新视图模型中的源属性:
<local:MyUserControl Template="{StaticResource TextBoxTemplate}"
NomPersonne="{Binding Name}"/>
您还应该在窗口中而不是在ResourceDictionary
中设置DataContext
:
<Window x:Class="ViewModel_defined_in_ControlTemplate.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ViewModel_defined_in_ControlTemplate"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Window.DataContext>
<local:MyViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<local:MyUserControl Template="{StaticResource TextBoxTemplate}"
NomPersonne="{Binding Name}"/>
<Button Content="Click me!" Command="{Binding ChangeTextBoxContent}" Width="100" HorizontalAlignment="Left"/>
</StackPanel>
</Grid>
</Window>
为用户控件提供ViewModel是一个非常糟糕的主意。您刚刚偶然发现了这种方法的许多问题之一。在ViewModel中无法定义DependecProperty,代码隐藏是唯一的方法 为了在代码隐藏和ViewModel之间同步数据,您必须在代码隐藏中订阅ViewModel的PropertyChanged,并且每当ViewModel中的值更改时,更新代码隐藏中相应的DependencyProperties。这也必须以另一种方式进行。当DependencyProperty更改时,必须在ViewModel中更新它。要做到这一点并非不可能,但确实很难看(相信我,我已经做到了;以后再也不会这样了) 另一个问题是将UserControl的DataContext(在代码隐藏或XAML中)设置为ViewModel。如果直接在UserControl上设置,绑定将无法工作。解决方法是设置UserControl的第一个子项的DataContext(同样,不要这样做) 带有ViewModel的UserControl是一个非常糟糕的主意。但这并不是说你的代码应该包含所有的代码。您总是可以将执行某些高级逻辑的方法提取到它们各自的类中。静态方法可以在任何地方调用,甚至可以在代码后面调用
<local:MyUserControl Template="{StaticResource TextBoxTemplate}"
NomPersonne="{Binding Name}"/>
public class MyViewModel : ViewModelBase
{
public RelayCommand ChangeTextBoxContent = new RelayCommand(() =>
{
Name = "...":
}, () => true);
private string _name;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged(); }
}
...
}
<Window x:Class="ViewModel_defined_in_ControlTemplate.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ViewModel_defined_in_ControlTemplate"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Window.DataContext>
<local:MyViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<local:MyUserControl Template="{StaticResource TextBoxTemplate}"
NomPersonne="{Binding Name}"/>
<Button Content="Click me!" Command="{Binding ChangeTextBoxContent}" Width="100" HorizontalAlignment="Left"/>
</StackPanel>
</Grid>
</Window>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ViewModel_defined_in_ControlTemplate">
<ControlTemplate x:Key="TextBoxTemplate" TargetType="{x:Type local:MyUserControl}">
<Grid>
<TextBox Width="50" HorizontalAlignment="Left"
Text="{TemplateBinding NomPersonne}"/>
</Grid>
</ControlTemplate>
</ResourceDictionary>