2013-10-30 87 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