C# 如何为WPF中具有视图模型的用户控件设置参数
在WPF中,我有一个包含用户控件的窗口。窗口和用户控件都有一个视图模型。我想将一个参数从窗口的VM传递到UC的VM。我看了很多遍之后,还没找到办法 窗口XAML将其数据上下文设置为其VM。UC包含参数的自定义依赖项属性。我想使用C# 如何为WPF中具有视图模型的用户控件设置参数,c#,wpf,xaml,C#,Wpf,Xaml,在WPF中,我有一个包含用户控件的窗口。窗口和用户控件都有一个视图模型。我想将一个参数从窗口的VM传递到UC的VM。我看了很多遍之后,还没找到办法 窗口XAML将其数据上下文设置为其VM。UC包含参数的自定义依赖项属性。我想使用SetBinding将DP绑定到UC VM 如果我将UC数据上下文设置为其VM,则参数绑定不起作用。如果我没有设置UC数据上下文,那么参数绑定可以工作,但是UC VM没有被引用 如何传递参数并绑定到UC VM UC XAML <UserControl x:Name=
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>
<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>
窗口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>
<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>
我想使用SetBinding将DP绑定到UC VM
这真的是一个要求吗?要求目标属性是依赖项属性,这反过来又要求目标对象是依赖项对象。您的视图模型对象不是依赖项对象,当然,它的任何属性都不是依赖项属性
实现这一目标需要对代码进行比显然需要的更大的更改
如果我将UC数据上下文设置为其VM,则参数绑定不起作用
为什么不呢?您没有显示尝试此操作的代码,因此很难理解此处的含义。无论如何,让用户控件设置自己的DataContext
不是一个好主意。该属性是公共的,您不希望将实现细节公开给客户端代码。如果客户端代码将DataContext
设置为错误的内容,那么这样做会导致bug,从而禁用UserControl
中的所有内容
但是也就是说,如果“参数绑定”是指main窗口中的绑定
XAML,将{binding PropWindowViewModel}
分配给用户控件的PropUserControlView
属性,那么只设置用户控件的DataContext
就不会影响到这一点。用户控件中仍然有dependency属性,用户控件中绑定的任何内容都应该仍然有效
最后,还不完全清楚为什么要将依赖项属性绑定到视图模型。在用户控件的XAML中,您可以(正如您已经做过的)直接绑定到用户控件的dependency属性。视图模型中不需要属性来复制它
也许您在视图模型的其他地方有代码想要响应此值的更改?这并不清楚,而且在不了解全部情况的情况下,很难给出最好的建议
综上所述,您在上面发布的代码可以进行一些小的修改。首先,您需要公开创建视图模型的TextBlock
,以便后面的用户控件代码可以访问它:
<TextBlock x:Name="textBlock1" Text="{Binding PropUserControlViewModel, FallbackValue=propUserControlViewModel 2}" FontWeight="Bold">
<TextBlock.DataContext>
<l:UserControl1ViewModel/>
</TextBlock.DataContext>
</TextBlock>
上述方法在您有限的示例中有效,但您可能希望为dependencPropertyChanged()
方法指定一个更具描述性的名称,具体到所讨论的实际属性
如果您确实选择以这种方式镜像视图模型中的依赖项属性,那么更好的方法是设置用户控件的根元素(即
网格
),使其数据上下文是您的视图模型,然后在XAML的其余部分中,仅绑定到视图模型。混合使用视图模型和依赖属性本身并不是错误的,但它确实引入了不一致性,这会使测试和维护代码变得更加困难。据我所知,您的意思是:-
1) 您有一个用户控件,它有自己的视图模型
2) 您有一个窗口,其中有自己的视图模型
您希望链接这两个参数,并将参数从WindowViewModel传递到UserControlViewModel
您可以做的是,在WindowViewModel中保留UserControlViewModel类型的属性(例如,UCViewModel
),并将XAML中用户控件的datacontext设置为
<local:UserControl1 DataContext="{Binding UCViewModel}" .../>
现在,您可以通过WindowViewModel访问UserControlViewModel中的任何内容,您可以设置任何属性值或从WindowViewModel向UserControlViewModel传递任何参数
如果您需要代码参考,请告诉我。我们一直在以类似的方式使用用户控件,它工作得很好。“窗口和用户控件都有一个视图模型。我想将一个参数从窗口的VM传递到UC的VM。”这首先是错误的方法。UserControl永远不应该有自己的视图模型。相反,它应该公开绑定到“外部”视图模型的依赖项属性,该视图模型通过从其父元素继承值或在XAML中声明UserControl时直接分配DataContext属性传递给UserControl的DataContext。永远不要在自己的XAML或代码隐藏中显式设置UserControl的DataContext。谢谢。我们需要挫折:这对我来说太具体了。我只希望能够有绑定,链接窗口虚拟机与UC虚拟机。设置UC DataContext时,重新传递参数不起作用:请参阅我的问题。我知道有一些解决方法(我已经尝试过你描述的vm.approach),但我想知道绑定在整个过程中是否可以使用。我做了一次快速尝试,但没有成功。你能给出一个代码指针吗?在任何情况下,这都有窗口和UC VM之间的强引用的缺点,因此您无法独立于UC VM使用窗口。
<local:UserControl1 DataContext="{Binding UCViewModel}" .../>