2014-07-10 151 views
0

我正在處理由大量數據輸入表單組成的WPF應用程序。我已將這些表單中的每一個都公開爲單獨的用戶控件。所以,我有CustomerView(UserControl),CompaniesView(UserControl)。每個表格由用戶輸入的客戶名稱,公司名稱等字段組成,然後保存。WPF MVVM兩個用戶控件之間的通信

保存操作使用由「保存」,「刪除」和「關閉」選項組成的工具欄執行。我已經創建工具欄到一個單獨的UserControl中,並將其放在容器視圖/ shell視圖中。以下是將要闡明的事情的結構。

CONTAINER BEGINS 
-------------------------------------------------------------------- 

----------------------------------- 
THIS IS THE TOOLBAR 
---------------------------------- 
______________________________________ 


Data Entry forms are injected here on the fly 


______________________________________ 


--------------------------------------------------------------------- 
CONTAINER ENDS 

問題是,當我點擊工具欄上的保存按鈕,我不知道任何關於包含窗體的視圖。我需要獲取附加到該視圖的MVVM模型,以便保存它。

+0

您是否在使用棱鏡?通常,我在我的viewmodel中實現IActiveAware,區域管理器自動在我的ViewModel和View上設置IsActive。然後我創建一個「SaveCommand」這是一個CompositeCommand並註冊每個ViewModel的命令。當ViewModel處於活動狀態時,切換其命令的IsActive屬性,因此只調用正確的屬性。 – Alan

+0

是的,我正在使用棱鏡。雖然我對棱鏡和WPF是新手,但是我的知識是有限的。我一定會檢查出來。 –

回答

0

我用UserControls處理這個問題的方式是我的shell視圖模型將同時引用ToolbarViewModel和DataEntryViewModel。工具欄將爲每個可能的命令觸發一個事件,並且shell視圖模型將適當地處理事件。下面是一個示例:

在MainView中,爲每個可能的DataEntry視圖/視圖模型創建一個DataTemplate。然後將ContentPresenter綁定到DataEntryViewModel的基本類型的MainViewModel中的屬性。

<Window 
    //usual window declarations> 

    <Window.Resources> 
     <DataTemplate DataType="{x:Type vm:DataEntryViewModel}"> 
     <view:DataEntryView /> 
     </DataTemplate> 

     //more DataTemplates for other data entry views 
    </Window.Resources> 

    <Grid> 
     <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 

     <view:ToolbarView Grid.Row="0" 
         DataContext="{Binding ToolbarContext}" /> 
     <ContentPresenter Grid.Row="1" 
         Content="{Binding DataEntryContext}" /> 
    </Grid> 
</Window> 

DataEntryViewModel將爲工具欄可能要執行的所有不同的可能操作提供一種方法。爲了簡潔起見,我只提供了Save方法。

public interface IDataEntryViewModelBase 
{ 
    void Save(); 
} 

public abstract class DataEntryViewModelBase : ViewModelBase, IDataEntryViewModelBase 
{ 
    public virtual void Save() 
    { 
     //base save work 
    } 
} 

public class DataEntryViewModel : DataEntryViewModelBase 
{ 
    public override void Save() 
    { 
     base.Save(); 

     //unique save work 
    } 
} 

ToolbarViewModel爲每個可執行的命令都有一個事件。

public class ToolbarViewModel : ViewModelBase, IToolbarViewModel 
{ 
    //can just use EventArgs here if no need to pass data when this event fires 
    public event EventHandler<SaveExecutedArgs> SaveExecuted; 

    public ICommand CmdSave 
    { 
     get { return new RelayCommand(() => OnSaveExecuted()); } 
    } 

    protected void OnSaveExecuted() 
    { 
     var handler = SaveExecuted; 
     if (handler == null) return; 
     handler(this, new SaveExecutedArgs()); 
    } 
} 

MainViewModel具有工具欄DataContext的屬性和DataEntry DataContext的屬性。當分配ToolbarContext時,我爲工具欄公開的每個命令事件註冊一個方法。在事件處理程序中,我爲該事件調用DataEntryContext的適當方法。

public class MainViewModel : ViewModelBase 
{ 
    private IToolbarViewModel _toolbarContext; 
    public IToolbarViewModel ToolbarContext 
    { 
     get { return _toolbarContext; } 
     set { Set("ToolbarContext", ref _toolbarContext, value); } 
    } 

    private IDataEntryViewModelBase _dataEntryContext; 
    public IDataEntryViewModelBase DataEntryContext 
    { 
     get { return _dataEntryContext; } 
     set { Set("DataEntryContext", ref _dataEntryContext, value); } 
    } 

    public MainViewModel() 
    { 
     _toolbarContext = new ToolbarViewModel(); 
     _toolbarContext.SaveExecuted += ToolbarContext_SaveExecuted; 
     _dataEntryContext = new DataEntryViewModel(); 
    } 

    private void ToolbarContext_SaveExecuted(object sender, SaveExecutedArgs e) 
    { 
     //can change this to popup a warning or however you want to handle it 
     //under the circumstance that DataEntryContext is null 
     if (DataEntryContext == null) return; 

     DataEntryContext.Save(); 
    } 
}