2016-01-22 92 views
2

在MS VS 2015 Professional中,我使用Catel作爲MVVM框架開發C#WPF MVVM應用程序。我的問題是我不知道如何使用按鈕在一個窗口中實現多個視圖之間的切換。下面我簡要介紹一下我的應用。 MainWindow有三個按鈕如何在WPF MVVM Catel應用程序中切換多個視圖?

<catel:Window x:Class="FlowmeterConfigurator.Views.MainWindow" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:catel="http://catel.codeplex.com" 
      ResizeMode="CanResize"> 

    <catel:StackGrid x:Name="LayoutRoot"> 
     <catel:StackGrid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto"/> 
     </catel:StackGrid.RowDefinitions> 

     <ToolBar> 
      <Button Name="btnConnectDisconnect" Content="Connect/Disconnect"/> 
      <Button Name="btnFieldSettings" Content="Field Settings"/> 
      <Button Name="btnCalibration" Content="Flowmeter Calibration"/> 
     </ToolBar> 
    </catel:StackGrid> 
</catel:Window> 

應用程序MainWindow有一個ViewModel。爲簡潔起見,我不在這裏展示。除了MainWindow之外,我的應用程序中還有三個視圖:ConnectDisconnectView,CalibrationView和FieldSettingsView。爲了簡潔起見,我僅在這裏展示其中的一個(FieldSettingsView),因爲所有其他人都是以catel:UserControl爲基礎以相同的方式創建的。

<catel:UserControl x:Class="FlowmeterConfigurator.Views.FieldSettingsView" 
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       xmlns:catel="http://catel.codeplex.com"> 

    <catel:StackGrid> 
     <catel:StackGrid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
     </catel:StackGrid.RowDefinitions> 
     <catel:StackGrid.ColumnDefinitions> 
      <ColumnDefinition/> 
      <ColumnDefinition/> 
     </catel:StackGrid.ColumnDefinitions> 

     <Label Grid.Row="0" Grid.Column="0" Content="Flowmeter Serial Number"/> 
     <TextBox Name="SerialNumber" Grid.Row="0" Grid.Column="1"/> 
    </catel:StackGrid> 

</catel:UserControl> 

每個視圖都有一個模型。我僅在這裏展示其中的一種模型,因爲它們都以相同的方式創建。

using Catel.Data; 
namespace FlowmeterConfigurator.Models 
{ 
    /// <summary> 
    /// Field Settings Model. 
    /// </summary> 
    public class FieldSettingsModel : SavableModelBase<FieldSettingsModel> 
    { 
     /// <summary> 
     /// Returns flowmeter serial number. 
     /// </summary> 
     public string SerialNumber 
     { 
      get { return GetValue<string>(SerialNumberProperty); } 
      set { SetValue(SerialNumberProperty, value); } 
     } 

    /// <summary> 
    /// Register SerialNumber property. 
    /// </summary> 
    public static readonly PropertyData SerialNumberProperty = RegisterProperty("SerialNumber", typeof(string), null); 
    } 
} 

每個視圖都有一個ViewModel。我只在這裏展示其中的一種ViewModel,因爲它們都以相同的方式創建。

using Catel; 
using Catel.Data; 
using Catel.MVVM; 
using FlowmeterConfigurator.Models; 

namespace FlowmeterConfigurator.ViewModels 
{ 
    /// <summary> 
    /// Field settings ViewModel. 
    /// </summary> 
    public class FieldSettingsViewModel : ViewModelBase 
    { 
     /// <summary> 
     /// Creates a FieldSettingsViewModel instance. 
     /// </summary> 
     /// <param name="fieldSettingsModel">Field settings Model.</param> 
     public FieldSettingsViewModel(FieldSettingsModel fieldSettingsModel) 
     { 
      Argument.IsNotNull(() => fieldSettingsModel); 
      FieldSettings = fieldSettingsModel; 
     } 

     /// <summary> 
     /// Returns or sets Field Settings Model. 
     /// </summary> 
     [Model] 
     public FieldSettingsModel FieldSettings 
     { 
      get { return GetValue<FieldSettingsModel>(FieldSettingsProperty); } 
      set { SetValue(FieldSettingsProperty, value); } 
     } 

     /// <summary> 
     /// Here I register FieldSettings property. 
     /// </summary> 
     public static readonly PropertyData FieldSettingsProperty = RegisterProperty("FieldSettings", typeof(FieldSettingsModel), null); 

     /// <summary> 
     /// Returns or sets flowmeter serial number. 
     /// </summary> 
     [ViewModelToModel("FieldSettings")] 
     public string SerialNumber 
     { 
      get { return GetValue<string>(SerialNumberProperty); } 
      set { SetValue(SerialNumberProperty, value); } 
     } 

     /// <summary> 
     /// Here I register SerialNumber property. 
     /// </summary> 
     public static readonly PropertyData SerialNumberProperty = RegisterProperty("SerialNumber", typeof(string), null); 
    } 
} 

直接在我的應用程序加載後,必須顯示ConnectDisconnectView。然後用戶可以使用MainWindow工具欄上的按鈕隨意切換視圖。視圖之間的切換必須按照以下方式進行:如果(例如)當前顯示的視圖是「ConnectDisconnectView」,並且用戶按下了「Field Settings」按鈕,則「MainDisconnectView」視圖必須從MainWindow消失並且必須出現「FieldSettingsView」視圖,必須顯示在MainWindow中。等等。即在MainWindow工具欄中按下適當的按鈕(例如「流量計校準」)時,必須在MainWindow中顯示相應的視圖(CalibrationView),並且不能顯示其他視圖。我怎樣才能在我的應用程序中實現這種功能?您的幫助將非常感激。

P.S.當然,正如您所看到的,爲了簡潔明瞭,視圖的數量和內容在此縮小。在現實世界中,我的應用程序中的視圖數量約爲20 - 25,並且它們必須包含複雜的圖形和表格信息。

+0

幫你一個忙,並使用Catel.Fody。然後,您可以將Catel屬性編寫爲常規屬性。 –

+0

我的視圖切換任務可以通過Catel.Foby解決嗎? – user3769902

回答

1

解決此問題的一種方法是使用Prism的區域。 Catel provides an extension for Prism,以便您可以在特定區域中激活視圖模型。

+0

不幸的是我之前從未使用Prism。如果有人給我一個在我的情況下在多個視圖間切換的案例,我將非常感激。 – user3769902

+0

是否在NET4.6中提供了Prism擴展附帶的UI組合功能? – user3769902

+0

我嘗試使用Catel.Extensions.Prism時出現以下錯誤:「無法找到類型或命名空間名稱'IUCompositionService'(您是否缺少using指令或程序集引用?)「 – user3769902

4

首先我告訴你XAML代碼:

<catel:Window.Resources> 
    <catel:ViewModelToViewConverter x:Key="ViewModelToViewConverter" /> 
</catel:Window.Resources> 

<catel:StackGrid x:Name="LayoutRoot"> 
    <ContentControl Content="{Binding CurrentPage, Converter={StaticResource ViewModelToViewConverter}}" /> 

    <ToolBar> 
    <Button Name="btnConnectDisconnect" Command={Binding Connect} Content="Connect/Disconnect"/> 
     <Button Name="btnFieldSettings" Command={Binding Field} Content="Field Settings"/> 
     <Button Name="btnCalibration" Command={Binding Calibration} Content="Flowmeter Calibration"/> 
    </ToolBar> 
</catel:StackGrid> 

然後在C#代碼,你需要這樣的:

using Catel.Data; 
using Catel.MVVM; 
using System.Threading.Tasks; 

public class MainWindowViewModel : ViewModelBase 
{ 
    public MainWindowViewModel() 
    { 
     this.Connect = new Command(HandleConnectCommand); 
     this.Field = new Command(HandleFieldCommand); 
     this.Calibration = new Command(HandleCalibrationCommand); 

     this.CurrentPage = new ConnectViewModel(); 
    } 

    /// <summary> 
    /// Gets or sets the CurrentPage value. 
    /// </summary> 
    public IViewModel CurrentPage 
    { 
     get { return GetValue<IViewModel>(CurrentPageProperty); } 
     set { SetValue(CurrentPageProperty, value); } 
    } 

    /// <summary> 
    /// Register the CurrentPage property so it is known in the class. 
    /// </summary> 
    public static readonly PropertyData CurrentPageProperty = RegisterProperty("CurrentPage", typeof(IViewModel), null); 

    public Command Connect { get; private set; } 

    public Command Field { get; private set; } 

    public Command Calibration { get; private set; } 

    protected override async Task InitializeAsync() 
    { 
     await base.InitializeAsync(); 
     // TODO: subscribe to events here 
    } 

    protected override async Task CloseAsync() 
    { 
     // TODO: unsubscribe from events here 
     await base.CloseAsync(); 
    } 

    private void HandleCalibrationCommand() 
    { 
     this.CurrentPage = new CalibrationViewModel(); 
    } 

    private void HandleFieldCommand() 
    { 
     this.CurrentPage = new FieldViewModel(); 
    } 

    private void HandleConnectCommand() 
    { 
     this.CurrentPage = new ConnectViewModel(); 
    } 
} 

當你啓動應用程序當前頁是用來裝載數據上下文ConnectViewModel()。然後使用按鈕中的命令,您可以更改另一個視圖模型的日期上下文。

+0

不要忘記將我的答案標記爲已選中如果它對你有好處。 – evelikov92