2013-10-30 86 views
2

我试图找到两个用户控件之间进行通信的最佳方式。我有一个主要的XAML窗口,其中包含两个用户控件,它们又包含各种控件。每个用户控件背后的代码只需将DataContext设置为与其关联的View Model。视图模型包含绑定到控件的对象。 我想要做的是在用户控件1中的列表框改变选择时捕获,新的选定项目显示在用户控件2的编辑框中。当我使用视图模型时,我无法声明依赖属性所以我想知道什么是可接受的方式来执行此操作? 我附上了一些基本的代码来展示我如何设置控件。WPF用户控件之间的通信

主窗口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的选择的价值? 谢谢

回答

4

虽然我明白,你是问如何UserControl小号之间的沟通,我会建议,答案是沟通的视图模型之间。这可以使用delegate对象轻松实现。一般来说,你需要有一个父视图模型,这对于两个子视图模型是通用的。

我最近回答了一个类似的问题,所以我不会重复的答案。相反,我会请你看看StackOverflow上的Passing parameters between viewmodels这篇文章的答案,它用代码示例解释了解决方案。


UPDATE >>>

当我说你需要一个共同的父母你的孩子视图模型,我的意思并不是任何与继承。我的意思是父母拥有每个子视图模型的变量实例...父母实例化子视图模型。

而不是在视图代码创建背后的视图模型的实例,你可以做到这一点父视图模型和视图模型连接到这样的观点:

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 

无论采用哪种方式,如果您要能够将它们与处理程序“连接在一起”,则需要从父视图访问这些视图模型。

+0

谢里登,谢谢你的回答,我认为这是一个非常整洁的解决方案。我只是在理解视图模型对象的实例化方面苦苦挣扎。在你的例子中,父视图模型创建子视图模型的实例,如果子视图模型是从父视图模型继承的(你没有说明这一点,但我假设这就是你的意思),不是这造成了问题。另外,我在后面的View代码中创建View模型的实例,以便我可以为它们设置DataContext。再次感谢。 – user2936676

1

我建议你,只有一个ViewModel并将DataContext绑定到MainWindow.xaml,而不是对每个UserControl执行。

您还应该在您的ViewModel中实现INotifyPropertyChanged,以在您更改代码或ViewModel中的值时通知UI。

+0

嗨Kumareshan,我想我没有解释说我保持这个例子非常简单明了。实际上,我将拥有大量的用户控件,并有一个视图模型会变得非常混乱。我没有显示INotifyPropertyChanged的实现,以使代码尽可能小,但我应该在我的问题中解释这一点。谢谢。 – user2936676

0

也许你应该考虑一下你在用户控件中没有依赖属性的自我限制。 MVVM适合整体架构,但如果将其放入每个课程和控件中,您都可以做到这一点。

如果您的用户控件只是用户的控件,则它们应该如此操作。我从来没有与TextBoxViewModel或ButtonViewModel进行通信,这些都是我简单使用的控件。也许你也很简单,不需要它自己的viewmodel。然后,您可以像所有其他控件一样使用依赖属性进行通信。

+0

公平点。这引发了关于视图中应该有多少代码的争论。这是我试图将所有处理放在View Model中的第一个项目,并且在某些领域发现了一些困难。 – user2936676