我正在尝试找到两个用户控件之间进行通信的最佳方式。我有一个主XAML窗口,其中包含两个用户控件,而这些控件又包含各种控件。每个用户控件背后的代码只是将DataContext设置为与其关联的视图模型。视图模型包含绑定到控件的对象。 我想要做的是捕获当用户控件1中的列表框更改选择时,新选择的项目将显示在用户控件2的编辑框中。因为我正在使用视图模型,所以我无法声明依赖属性我想知道执行此操作的可接受方式是什么? 我附上了一些基本代码来说明我是如何设置控件的。
主窗口XAML
<Window x:Class="CommsTest.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CommsTest.View"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:UserControl1 />
<local:UserControl2 />
</Grid>
UserControl1 XAML
<UserControl x:Class="CommsTest.View.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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<ComboBox Height="23" HorizontalAlignment="Left" Margin="50,110,0,0" Name="comboBox1" VerticalAlignment="Top" Width="199" ItemsSource="{Binding Combo1}" />
</Grid>
UserControl1ViewModel.cs
class UserControl1ViewModel
{
private ObservableCollection<string> combo1 = new ObservableCollection<string>();
public ObservableCollection<string> Combo1
{
get { return combo1; }
}
}
UserControl2.XAML
<UserControl x:Class="CommsTest.View.UserControl2"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBox Height="23" HorizontalAlignment="Left" Margin="63,84,0,0" Name="textBox1" VerticalAlignment="Top" Width="170" Text="{Binding Path=Text1}" />
</Grid>
UserControl2ViewModel.cs
class UserControl2ViewModel
{
private string text1;
public string Text1
{
get { return text1; }
set { text1 = value; }
}
}
如何让UserControl2.Text1成为UserControl2.Combo1的选定值? 感谢
答案 0 :(得分:5)
虽然我知道您在询问如何在 UserControl
之间进行通信,但我建议答案是在视图模型之间进行通信。使用delegate
个对象可以轻松实现这一点。通常,您需要具有两个子视图模型共有的父视图模型。
我最近回答了类似的问题,所以我不会重复答案。相反,我想请你看一下StackOverflow上Passing parameters between viewmodels帖子的答案,它解释了代码示例的解决方案。
更新&gt;&gt;&gt;
当我说你的孩子视图模型需要一个共同的父母时,我并不意味着与继承有关。我只是说父项拥有每个子视图模型的变量实例...父实例化子视图模型。
您可以在父视图模型中执行此操作,并将视图模型连接到这样的视图,而不是在后面的视图代码中创建视图模型实例:
在Resources
:
<DataTemplate DataType="{x:Type ViewModels:MainViewModel}">
<Views:MainView />
</DataTemplate>
...
<DataTemplate DataType="{x:Type ViewModels:UsersViewModel}">
<Views:UsersView />
</DataTemplate>
然后您只需要显示视图模型的实例,并显示相应的视图:
在ParentView
:
<ContentControl Content="{Binding ViewModel}" />
在ParentViewModel
:
public BaseViewModel ViewModel { get; set; } // Implement INotifyPropertyChanged
然后当您想要显示新视图时:
ViewModel = new UsersViewModel();
如果您的孩子观点没有BaseViewModel
和/或不可互换,那么您可以为每个观点添加一个属性:
public MainViewmodel MainViewModel { get; set; } // Implement INotifyPropertyChanged
public UsersViewmodel UsersViewModel { get; set; } // properly for these properties
无论哪种方式,如果您希望能够与处理程序“将它们连接在一起”,您将需要从父视图访问这些视图模型。
答案 1 :(得分:1)
我建议你只有一个ViewModel并将DataContext绑定到MainWindow.xaml,而不是对每个UserControl执行。
您还应该在ViewModel中实现INotifyPropertyChanged
,以便在您从代码或ViewModel更改值时通知UI。
答案 2 :(得分:0)
也许你应该考虑一下你在用户控件中没有依赖属性的自我限制。 MVVM对于整个架构来说很不错,但是如果你把它放到每个类中并控制你打算做的话,你可以过度使用它。
如果您的用户控件只是用户的控件,则他们应该这样做。我从来没有与TextBoxViewModel或ButtonViewModel进行通信,这些是我简单使用的控件。也许你的很简单,也不需要它自己的viewmodel。然后,您可以像所有其他控件一样使用依赖项属性进行通信。