如何使用DataTemplate的DataTriggers基于Window的ViewModel属性更改ContentControl的Content属性,该属性是枚举值

时间:2013-01-03 23:42:53

标签: wpf enums views datatemplate datatrigger

我请求你帮助解决一些简单的说法,而且很可能只是简单地完成但目前不适合我。 我正在开发的应用程序看起来像使用FluidUI控件集的Office 2013。 我想从Word / Access实现视图切换器,其中功能区上有视图选项卡,并且有按钮可以切换视图。 我认为将整个View对象存储在我的ViewModel的属性CurrentView中是错误的方式,我尝试使这个应用程序尽可能纯粹的MVVM。这个应用程序更像是“如何使用MVVM编写应用程序”因为我还在学习WPF。 好。所以我的窗口(MainWindowModern是正确的)有流体功能区。切换视图有3个按钮(我称之为编辑器)。 他们所做的是更改MainWindowModern的ViewModel的CurrentView属性并为其设置新的枚举值。这部分设置新的枚举值已经完成并且有效。 现在。窗口的主体只是ContentControl。现在我想基于DataContext.CurrentView属性值更改此ContentControl的Content属性。就像我以前说过的那样。我不想在视图的c#(我在C#中编写这个应用程序)文件中执行任何代码隐藏。 唯一不起作用的是改变ContentControl Content属性。我正在尝试使用DataTemplates和DataTemplate.Triggers

现在这就是我到目前为止所做的事情(没有不相关的代码)。

Window的XAML

<Fluent:MetroWindow
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Fluent="clr-namespace:Fluent;assembly=Fluent"
    xmlns:localVM="clr-namespace:MVVMTest.ViewModels"
    xmlns:local="clr-namespace:MVVMTest"
    x:Class="MVVMTest.Views.MainWindowModern"
    x:Name="ThisWindow"
    Title="Dialogue Editor (Modern UI Version)"
    Width="1280" Height="480"
    RibbonThemeColor="Red" WindowState="Maximized"
    Icon="..\Assets\App\AppIcon_32x32.png">

    <Window.Resources>
        <DataTemplate x:Key="CharactersEditorTemplate">
            <TextBlock Text="Characters Editor Template Body" />
        </DataTemplate>
        <DataTemplate x:Key="ChaptersEditorTemplate">
            <TextBlock Text="Chapters Editor Template Body" />
        </DataTemplate>
        <DataTemplate x:Key="ConversationsEditorTemplate">
            <TextBlock Text="Conversations Editor Template Body" />
        </DataTemplate>
        <DataTemplate x:Key="aaa" DataType="{x:Type ContentControl}" >
            <TextBlock Text="{Binding ElementName=ThisWindow, Path=DataContext.CurrentView}" />
            <DataTemplate.Triggers>
                <!--<DataTrigger Binding="{Binding CurrentView}">
                    <DataTrigger.Value>
                        <localVM:EditorView>CharactersEditor</localVM:EditorView>
                    </DataTrigger.Value>
                    <Setter Property="Content" Value="{StaticResource CharactersEditorTemplate}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding CurrentView}">
                    <DataTrigger.Value>
                        <localVM:EditorView>ChaptersEditor</localVM:EditorView>
                    </DataTrigger.Value>
                    <Setter Property="Content" Value="{StaticResource ChaptersEditorTemplate}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding CurrentView}">
                    <DataTrigger.Value>
                        <localVM:EditorView>ConversationsEditor</localVM:EditorView>
                    </DataTrigger.Value>
                    <Setter Property="Content" Value="{StaticResource ConversationsEditorTemplate}" />
                </DataTrigger>-->

                <DataTrigger Binding="{Binding ElementName=ThisWindow, Path=DataContext.CurrentView}">
                    <DataTrigger.Value>
                        <localVM:EditorView>ChaptersEditor</localVM:EditorView>
                    </DataTrigger.Value>
                    <DataTrigger.Setters>
                        <Setter Property="Content" Value="{StaticResource ChaptersEditorTemplate}" />
                    </DataTrigger.Setters>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </Window.Resources>

    <Window.DataContext>
        <localVM:MainWindowVM />
    </Window.DataContext>

    <DockPanel x:Name="LayoutRoot" LastChildFill="True">
        <Fluent:Ribbon DockPanel.Dock="Top">

            <Fluent:RibbonTabItem Header="VIEW" Fluent:KeyTip.Keys="V" ReduceOrder="ViewsRibbonGroupBox, ViewsRibbonGroupBox, ViewsRibbonGroupBox">

                <Fluent:RibbonGroupBox Name="ViewsRibbonGroupBox" Header="Views">

                    <Fluent:Button Name="CharactersViewButton" 
                                   Header="Characters" 
                                   LargeIcon="..\Assets\Ribbon\View\CharacterEditorIcon_32x32.png"
                                   Icon="..\Assets\Ribbon\View\CharacterEditorIcon_32x32.png"
                                   Command="{Binding SwitchToCharactersEditorCommand}" >
                        <Fluent:Button.ToolTip>
                            <Fluent:ScreenTip
                                Image="..\Assets\Ribbon\View\CharacterEditorIcon_32x32.png"
                                Title="Characters Editor"
                                Text="Changes current view to Characters Editor view.&#x0a;&#x0a;In this view user can:&#x0a;&#x2022; List existing characters&#x0a;&#x2022; Create new characters&#x0a;&#x2022; Edit existing characters&#x0a;&#x2022; Delete existing characters&#x0a;&#x0a;It is also possible to manage character's emotions in this view." />
                        </Fluent:Button.ToolTip>
                    </Fluent:Button>

                    <Fluent:Button Name="ChaptersViewButton" 
                                   Header="Chapters" 
                                   LargeIcon="..\Assets\Ribbon\View\ChapterEditorIcon_32x32.png"
                                   Icon="..\Assets\Ribbon\View\ChapterEditorIcon_32x32.png"
                                   Command="{Binding SwitchToChaptersEditorCommand}" >
                        <Fluent:Button.ToolTip>
                            <Fluent:ScreenTip
                                Image="..\Assets\Ribbon\View\ChapterEditorIcon_32x32.png"
                                Title="Chapters Editor"
                                Text="Changes current view to Chapters Editor view.&#x0a;&#x0a;In this view user can:&#x0a;&#x2022; List existing chapters&#x0a;&#x2022; Create new chapters&#x0a;&#x2022; Edit existing chapters&#x0a;&#x2022; Delete existing chapters&#x0a;&#x0a;It is also possible to manage chapters's missions in this view." />
                        </Fluent:Button.ToolTip>
                    </Fluent:Button>

                    <Fluent:Button Name="ConversationsViewButton" 
                                   Header="Conversations" 
                                   LargeIcon="..\Assets\Ribbon\View\ConversationEditorIcon_32x32.png"
                                   Icon="..\Assets\Ribbon\View\ConversationEditorIcon_32x32.png"
                                   Command="{Binding SwitchToConversationsEditorCommand}" >
                        <Fluent:Button.ToolTip>
                            <Fluent:ScreenTip
                                Image="..\Assets\Ribbon\View\ConversationEditorIcon_32x32.png"
                                Title="Conversations Editor"
                                Text="Changes current view to Conversations Editor view.&#x0a;&#x0a;In this view user can:&#x0a;&#x2022; List existing conversations&#x0a;&#x2022; Create new conversations&#x0a;&#x2022; Edit existing conversations&#x0a;&#x2022; Delete existing conversations&#x0a;&#x0a;It is also possible to manage conversations's statements and statement's stages in this view."
                                DisableReason="Please define at least one chapter with at least one mission in it to enable Conversations Editor.&#x0a;Also it would be helpful to define at least one character with at least one emotion.&#x0a;It is optional action but highly recommended." />
                        </Fluent:Button.ToolTip>
                    </Fluent:Button>

                </Fluent:RibbonGroupBox>
            </Fluent:RibbonTabItem>

        </Fluent:Ribbon>

        <ContentControl Name="MainContent" ContentTemplate="{StaticResource aaa}" />

    </DockPanel>
</Fluent:MetroWindow>

<Fluent:MetroWindow xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Fluent="clr-namespace:Fluent;assembly=Fluent" xmlns:localVM="clr-namespace:MVVMTest.ViewModels" xmlns:local="clr-namespace:MVVMTest" x:Class="MVVMTest.Views.MainWindowModern" x:Name="ThisWindow" Title="Dialogue Editor (Modern UI Version)" Width="1280" Height="480" RibbonThemeColor="Red" WindowState="Maximized" Icon="..\Assets\App\AppIcon_32x32.png"> <Window.Resources> <DataTemplate x:Key="CharactersEditorTemplate"> <TextBlock Text="Characters Editor Template Body" /> </DataTemplate> <DataTemplate x:Key="ChaptersEditorTemplate"> <TextBlock Text="Chapters Editor Template Body" /> </DataTemplate> <DataTemplate x:Key="ConversationsEditorTemplate"> <TextBlock Text="Conversations Editor Template Body" /> </DataTemplate> <DataTemplate x:Key="aaa" DataType="{x:Type ContentControl}" > <TextBlock Text="{Binding ElementName=ThisWindow, Path=DataContext.CurrentView}" /> <DataTemplate.Triggers> <!--<DataTrigger Binding="{Binding CurrentView}"> <DataTrigger.Value> <localVM:EditorView>CharactersEditor</localVM:EditorView> </DataTrigger.Value> <Setter Property="Content" Value="{StaticResource CharactersEditorTemplate}" /> </DataTrigger> <DataTrigger Binding="{Binding CurrentView}"> <DataTrigger.Value> <localVM:EditorView>ChaptersEditor</localVM:EditorView> </DataTrigger.Value> <Setter Property="Content" Value="{StaticResource ChaptersEditorTemplate}" /> </DataTrigger> <DataTrigger Binding="{Binding CurrentView}"> <DataTrigger.Value> <localVM:EditorView>ConversationsEditor</localVM:EditorView> </DataTrigger.Value> <Setter Property="Content" Value="{StaticResource ConversationsEditorTemplate}" /> </DataTrigger>--> <DataTrigger Binding="{Binding ElementName=ThisWindow, Path=DataContext.CurrentView}"> <DataTrigger.Value> <localVM:EditorView>ChaptersEditor</localVM:EditorView> </DataTrigger.Value> <DataTrigger.Setters> <Setter Property="Content" Value="{StaticResource ChaptersEditorTemplate}" /> </DataTrigger.Setters> </DataTrigger> </DataTemplate.Triggers> </DataTemplate> </Window.Resources> <Window.DataContext> <localVM:MainWindowVM /> </Window.DataContext> <DockPanel x:Name="LayoutRoot" LastChildFill="True"> <Fluent:Ribbon DockPanel.Dock="Top"> <Fluent:RibbonTabItem Header="VIEW" Fluent:KeyTip.Keys="V" ReduceOrder="ViewsRibbonGroupBox, ViewsRibbonGroupBox, ViewsRibbonGroupBox"> <Fluent:RibbonGroupBox Name="ViewsRibbonGroupBox" Header="Views"> <Fluent:Button Name="CharactersViewButton" Header="Characters" LargeIcon="..\Assets\Ribbon\View\CharacterEditorIcon_32x32.png" Icon="..\Assets\Ribbon\View\CharacterEditorIcon_32x32.png" Command="{Binding SwitchToCharactersEditorCommand}" > <Fluent:Button.ToolTip> <Fluent:ScreenTip Image="..\Assets\Ribbon\View\CharacterEditorIcon_32x32.png" Title="Characters Editor" Text="Changes current view to Characters Editor view.&#x0a;&#x0a;In this view user can:&#x0a;&#x2022; List existing characters&#x0a;&#x2022; Create new characters&#x0a;&#x2022; Edit existing characters&#x0a;&#x2022; Delete existing characters&#x0a;&#x0a;It is also possible to manage character's emotions in this view." /> </Fluent:Button.ToolTip> </Fluent:Button> <Fluent:Button Name="ChaptersViewButton" Header="Chapters" LargeIcon="..\Assets\Ribbon\View\ChapterEditorIcon_32x32.png" Icon="..\Assets\Ribbon\View\ChapterEditorIcon_32x32.png" Command="{Binding SwitchToChaptersEditorCommand}" > <Fluent:Button.ToolTip> <Fluent:ScreenTip Image="..\Assets\Ribbon\View\ChapterEditorIcon_32x32.png" Title="Chapters Editor" Text="Changes current view to Chapters Editor view.&#x0a;&#x0a;In this view user can:&#x0a;&#x2022; List existing chapters&#x0a;&#x2022; Create new chapters&#x0a;&#x2022; Edit existing chapters&#x0a;&#x2022; Delete existing chapters&#x0a;&#x0a;It is also possible to manage chapters's missions in this view." /> </Fluent:Button.ToolTip> </Fluent:Button> <Fluent:Button Name="ConversationsViewButton" Header="Conversations" LargeIcon="..\Assets\Ribbon\View\ConversationEditorIcon_32x32.png" Icon="..\Assets\Ribbon\View\ConversationEditorIcon_32x32.png" Command="{Binding SwitchToConversationsEditorCommand}" > <Fluent:Button.ToolTip> <Fluent:ScreenTip Image="..\Assets\Ribbon\View\ConversationEditorIcon_32x32.png" Title="Conversations Editor" Text="Changes current view to Conversations Editor view.&#x0a;&#x0a;In this view user can:&#x0a;&#x2022; List existing conversations&#x0a;&#x2022; Create new conversations&#x0a;&#x2022; Edit existing conversations&#x0a;&#x2022; Delete existing conversations&#x0a;&#x0a;It is also possible to manage conversations's statements and statement's stages in this view." DisableReason="Please define at least one chapter with at least one mission in it to enable Conversations Editor.&#x0a;Also it would be helpful to define at least one character with at least one emotion.&#x0a;It is optional action but highly recommended." /> </Fluent:Button.ToolTip> </Fluent:Button> </Fluent:RibbonGroupBox> </Fluent:RibbonTabItem> </Fluent:Ribbon> <ContentControl Name="MainContent" ContentTemplate="{StaticResource aaa}" /> </DockPanel> </Fluent:MetroWindow>

Window的ViewModel和枚举

using MVVMTest.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MVVMTest.ViewModels {
    public enum EditorView {
        CharactersEditor,
        ChaptersEditor,
        ConversationsEditor
    }

    public class MainWindowVM : ViewModelBase {

        public MainWindowVM() {
            this.init();
        }

        protected void init() {
            this.Characters = new ObservableCollection<CharacterVM>();

            this.initCommands();
            this.initSampleData();
        }

        protected void initSampleData() {
            Character ch1 = new Character() { Name = "Character 1" };
            Emotion e1 = new Emotion() { Name = "Emotion 1" };
            ch1.Emotions.Add(e1);
            CharacterVM ch1vm = new CharacterVM(ch1);
            this.Characters.Add(ch1vm);

            this.CurrentView = EditorView.ConversationsEditor;
        }

        protected void initCommands() {
            this.SwitchToCharactersEditorCommand = new RelayCommand(param => this.SwitchToCharactersEditor(), param => this.CanSwitchToCharactersEditor());
            this.SwitchToChaptersEditorCommand = new RelayCommand(param => this.SwitchToChaptersEditor(), param => this.CanSwitchToChaptersEditor());
            this.SwitchToConversationsEditorCommand = new RelayCommand(param => this.SwitchToConversationsEditor(), param => this.CanSwitchToConversationsEditor());
        }

        public ObservableCollection<CharacterVM> Characters { get; set; }

        protected EditorView _currentView;
        public EditorView CurrentView {
            get { return this._currentView; }
            set {
                if (this._currentView == value) {
                    return;
                }
                this._currentView = value;
                this.OnPropertyChanged("CurrentView");
            }
        }

        #region Commands

        #region View Tab

        #region Switch To Characters Editor
        public RelayCommand SwitchToCharactersEditorCommand { get; private set; }
        protected void SwitchToCharactersEditor() {
            this.CurrentView = EditorView.CharactersEditor;
        }
        protected bool CanSwitchToCharactersEditor() {
            if (this.CurrentView != EditorView.CharactersEditor) {
                return true;
            }
            return false;
        }
        #endregion Switch To Characters Editor

        #region Switch To Chapters Editor
        public RelayCommand SwitchToChaptersEditorCommand { get; private set; }
        protected void SwitchToChaptersEditor() {
            this.CurrentView = EditorView.ChaptersEditor;
        }
        protected bool CanSwitchToChaptersEditor() {
            if (this.CurrentView != EditorView.ChaptersEditor) {
                return true;
            }
            return false;
        }
        #endregion Switch To Chapters Editor

        #region Switch To Conversations Editor
        public RelayCommand SwitchToConversationsEditorCommand { get; private set; }
        protected void SwitchToConversationsEditor() {
            this.CurrentView = EditorView.ConversationsEditor;
        }
        protected bool CanSwitchToConversationsEditor() {
            if (this.CurrentView != EditorView.ConversationsEditor) {
                return true;
            }
            return false;
        }
        #endregion Switch To Conversations Editor

        #endregion View Tab

        #endregion Commands
    }
}

当这一切都完成后,下一步是添加动画来查看切换,就像在ModernUI Apps(或Android智能手机)上一样,所以旧内容越过窗口的边界,新内容来自另一面。如果不可能,那么我将停止只使用切换器。

2 个答案:

答案 0 :(得分:0)

好消息是,这实际上很容易做到,包括动画切换。你需要的是一个ItemsControl来托管你的子视图。 ItemsControl允许您使用DataTemplateSelector。因此,根据您的枚举值,您可以生成一些输出,选择器可以使用它来确定要使用的数据模板。尝试对选择器进行一些研究。如果您仍然感到困惑,请随时与我联系。祝好运。

答案 1 :(得分:0)

对于动画,我建议一个容纳你的子视图的容器控件。查看this link以获得一个非常可靠的实现,以帮助您入门。