【问题标题】:How to change ContentControl's Content property using DataTemplate's DataTriggers based on Window's ViewModel property which is an enum value如何使用基于 Window 的 ViewModel 属性的 DataTemplate 的 DataTriggers 更改 ContentControl 的 Content 属性,该属性是枚举值
【发布时间】:2013-01-03 23:42:53
【问题描述】:

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

这就是我到目前为止所得到的(没有不相关的代码)。

窗口的 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>

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 应用程序(或 Android 智能手机)上一样为视图开关添加动画,这样旧的内容就会越过窗口的边界而新的内容来自另一边。如果不可能,那么我将只使用工作切换器。

【问题讨论】:

    标签: wpf enums views datatemplate datatrigger


    【解决方案1】:

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

    【讨论】:

    • 感谢您的快速答复。
    • 1.为什么要使用 ItemsControl? ContentControl 也有 DataTemplateSelector。不能用它代替ItemsControl吗? 2. 当我认为真正需要做的是触发 DataTemplate 根据我可以访问的枚举值更改 ContentControl 的内容时,为什么要使用 DataTemplateSelector?我并不是说您的建议是坏的/错误的,但也许为什么我的方法不好?我也对你所说的选择器感到困惑。
    • 好的。不知何故,我设法创建了这个选择器,现在它可以工作了。但我使用的是 ContentControl 而不是 ItemsControl。第二个但是:我用过这个教程:switchonthecode.com/tutorials/…
    • 现在您谈到了动画。您能否提供一些有关如何完成此操作的资源?
    • 抱歉延迟回复。 ContentControl 是完全可行的。 ItemsControl 通常用于多条内容,而 ContentControl 用于单条内容。因为我整天都在处理倍数,所以这是我通常的控制方式。为混乱道歉。
    【解决方案2】:

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

    【讨论】:

    • 哦。对不起。我没有看到你发布第二个回复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-18
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    • 2010-12-20
    相关资源
    最近更新 更多