2011-10-12 85 views
1

假設我的WPF應用程序中有幾個視圖都顯示報表,但每個視圖顯示不同的報表。
我創建了一個基本的ViewModel,它包含了所有報告共有的所有內容。每個報告視圖都獲取自己的ViewModel,它是從基本ViewModel派生的。這些衍生的ViewModels具有以下職責:WPF視圖中的繼承/「組件化」

  1. 生成報表數據
  2. 格式的報表數據打印
  3. 提供性能報告的參數
  4. 爲可以在執行附加操作提供命令生成報告(可選)

這些都很好很簡潔,但是,視圖是一個完整的混亂。 基本上,每個視圖與只有一些微小的變化是相同的,例如:

  1. 提供不同的控制報告的參數
  2. 提供結合於命令用於附加動作的按鈕

我想實現以下目標:

  1. 有一個基本視圖定義所有的塞入f所有報告視圖都有共同點,類似於ASP.NET中的Site.master。這將包含搜索按鈕,打印按鈕,報告顯示在網格等...
  2. 具有具體視圖 - 每個報告一個 - 只定義了搜索參數的控件和其他操作的按鈕

如何做到這一點?谷歌搜索WPF母版頁提出了很多定製解決方案 - 當然必須有一個標準的方式?

+0

CAF GUI或PRISM使用這個主區域和本地區域的概念不是他們?你不能使用它? –

+0

我不使用這些框架,所以我不認爲我可以利用這個概念。 –

回答

2

在WPF中,佔位符ContentControl.ContentTemplate可以設置自動基於其DataTemplate.DataType如果Content被設置爲那個DataType實例。

http://www.japf.fr/2009/03/thinking-with-mvvm-data-templates-contentcontrol/

+0

+1,這通常是我所做的。我將爲所有ViewModel創建一個單一的視圖,並使用'ContentControls' /'DataTemplates'作爲特定​​的數據,或'DataTriggers' w /'ObjectToTypeConverter'返回一個對象的類型。然後我可以根據轉換的值是否等於'{x:Type local:MyViewModelA}來使用觸發器' – Rachel

1

我不確定這是創建合成視圖的標準方式,但我已經成功定義了一個主視圖(在我的情況下爲Window),其中包含視圖系列所需的常用控件,通過使用ContentControl作爲等價於ASP.NET主頁面中的ContentPlaceholder的方式,爲每個不同的子視圖注入不同的UserControl到主文件夾中。就我而言,我已經定義的所有子視圖實現一個接口:

public interface ISubView 
{ 
    BaseViewModel ViewModel { get; set; } 
} 

這讓我ApplicationController來處理,以顯示特定視圖的請求時,視圖模型推到子視圖。在顯示之前,通過主視圖上的setter屬性將子視圖與主視圖合成。

ApplicationController是集中開啓和關閉視圖任務的類;只要應用程序中的任何內容想要顯示特定視圖,就會詢問ApplicationController。當它接收到顯示特定視圖的請求時,它會查找並從內部「註冊表」中構造相應的子視圖和View Model子類,並將這些部分組合在一起。在應用程序啓動時,您創建ApplicationController並註冊ViewModel子類和View子類的組合。部分示例實現是:

public class ApplicationController 
{ 

    private IDictionary<string, Tuple<Func<ISubView>, Func<BaseViewModel>> _registry; 
    private Func<IShellWindow> _shellActivator; 

    public ApplicationController(Func<IShellWindow> shellActivator) 
    { 
     _registry = new Dictionary<string, Tuple<Func<ISubView>, Func<BaseViewModel>>(); 
     _shellActivator = shellActivator; 
    } 

    public void RequestShow(string viewName) 
    { 
     var shell = _shellActivator(); 
     var viewToModel = _registry[viewName]; 
     var view = viewToModel.Item1(); 
     var viewModel = viewToModel.Item2(); 
     view.ViewModel = viewModel; 
     shell.Display(view); 
    } 

    public Register(string name, Func<ISubView> subViewCreator, Func<ViewModel> viewModelCreator) 
    { 
     _registry.Add(name, new Tuple(subViewCreator, viewModelCreator)); 
    } 
} 

在外殼的Display方法(IShellView接口上定義),你會做這樣的事情:

public void Display(ISubView view) 
    { 
     contentHolder.Content = view; 
     DataContext = view.ViewModel; 
     Show(); 
    } 

的應用程序啓動將包括類似:

var appController = new ApplicationController(() => new ShellWindow()); 
appController.Register("EmployeesReport",() => new EmployeesReportView(),() => new EmployeesReportViewModel); 
appController.Register("OrdersReport",() => new OrdersReportView(),() => new OrdersReportViewModel()); 

//etc. 
+0

如何將用戶控件注入內容控件中?這是誰? –

+0

我已經擴展了答案以包含更多關於ApplicationController角色的內容。 –

+0

這對我來說就像一個自定義的CAF GUI實現。它具有維護註冊表視圖和它們的模型(在CAF GUI的情況下,這是區域)的外殼 –