【发布时间】:2018-01-21 17:39:59
【问题描述】:
在 WPF 中,我有一个包含用户控件的窗口。窗口和用户控件各有一个视图模型。我想将一个参数从窗口的 VM 传递给 UC 的 VM。经过相当多的寻找,我还没有找到方法。
窗口 XAML 将其数据上下文设置为其 VM。 UC 包含参数的自定义依赖属性。我想使用SetBinding将DP绑定到UC VM。
如果我将 UC 数据上下文设置为其 VM,则参数绑定不起作用。如果我不设置 UC 数据上下文,则参数绑定有效,但未引用 UC VM。
如何传递参数并绑定到 UC VM?
UC XAML
<UserControl x:Name="userControl" x:Class="Test_Paramaterized_UserControl_with_MVVM.UserControl1"
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:Test_Paramaterized_UserControl_with_MVVM"
xmlns:view="clr-namespace:Daavlin.SmartTouch.STUV_WPF.View"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Margin="10">
<Border BorderThickness="3" BorderBrush="Black" Padding="10">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock Text="UserControl1 View: "/>
<TextBlock Text="{Binding ElementName=userControl, Path=PropUserControlView, Mode=OneWay}" FontWeight="Bold"/>
</StackPanel>
<Rectangle Height="5"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="UserControl1 ViewModel: " />
<TextBlock Text="{Binding PropUserControlViewModel, FallbackValue=propUserControlViewModel 2}" FontWeight="Bold">
<TextBlock.DataContext>
<local:UserControl1ViewModel/>
</TextBlock.DataContext>
</TextBlock>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</UserControl>
UC 代码隐藏和虚拟机
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public string PropUserControlView { get => (string)GetValue(PropUserControlViewProperty); set => SetValue(PropUserControlViewProperty, value); }
public static readonly DependencyProperty PropUserControlViewProperty =
DependencyProperty.Register(nameof(PropUserControlView), typeof(string), typeof(UserControl1),
new PropertyMetadata(null, DependencyPropertyChanged));
private static void DependencyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var x = dependencyPropertyChangedEventArgs.NewValue;
}
}
public class UserControl1ViewModel : ObservableObject
{
public string PropUserControlViewModel { get => _propUserControlViewModel; set => SetField(ref _propUserControlViewModel, value); }
private string _propUserControlViewModel = "value from UserControl-ViewModel";
}
窗口 XAML
<Window x:Class="Test_Paramaterized_UserControl_with_MVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test_Paramaterized_UserControl_with_MVVM"
Title="MainWindow" >
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid VerticalAlignment="Top" >
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Margin="20">
<StackPanel Orientation="Horizontal">
<TextBlock Text="MainWindow1 ViewModel: "/>
<TextBox Text="{Binding PropWindowViewModel, UpdateSourceTrigger=PropertyChanged}" FontWeight="Bold"/>
</StackPanel>
<Rectangle Height="10"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="UserControl1 (fixed value Fixed): " VerticalAlignment="Center"/>
<local:UserControl1 PropUserControlView="Fixed"/>
</StackPanel>
<Rectangle Height="10"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="UserControl1 (bound to MainWindows VM): " VerticalAlignment="Center"/>
<local:UserControl1 PropUserControlView="{Binding PropWindowViewModel}"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
窗口代码隐藏和虚拟机
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class MainWindowViewModel : ObservableObject
{
public string PropWindowViewModel { get => _propWindowViewModel; set => SetField(ref _propWindowViewModel, value); }
private string _propWindowViewModel = "valuefrom Window-VIewModel";
}
【问题讨论】:
-
"窗口和用户控件各有一个视图模型。我想将一个参数从窗口的 VM 传递给 UC 的 VM。"这首先是错误的方法。 UserControl 永远不应该有自己的视图模型。相反,它应该公开绑定到“外部”视图模型的依赖属性,该视图模型通过从其父元素的值继承或通过在 XAML 中声明 UserControl 时直接分配 DataContext 属性传递给 UserControl 的 DataContext。永远不要在自己的 XAML 或代码中显式设置 UserControl 的 DataContext。