我请求你帮助解决一些简单的说法,而且很可能只是简单地完成但目前不适合我。 我正在开发的应用程序看起来像使用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.

In this view user can:
• List existing characters
• Create new characters
• Edit existing characters
• Delete existing characters

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.

In this view user can:
• List existing chapters
• Create new chapters
• Edit existing chapters
• Delete existing chapters

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.

In this view user can:
• List existing conversations
• Create new conversations
• Edit existing conversations
• Delete existing conversations

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.
Also it would be helpful to define at least one character with at least one emotion.
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.

In this view user can:
• List existing characters
• Create new characters
• Edit existing characters
• Delete existing characters

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.

In this view user can:
• List existing chapters
• Create new chapters
• Edit existing chapters
• Delete existing chapters

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.

In this view user can:
• List existing conversations
• Create new conversations
• Edit existing conversations
• Delete existing conversations

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.
Also it would be helpful to define at least one character with at least one emotion.
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智能手机)上一样,所以旧内容越过窗口的边界,新内容来自另一面。如果不可能,那么我将停止只使用切换器。
答案 0 :(得分:0)
好消息是,这实际上很容易做到,包括动画切换。你需要的是一个ItemsControl来托管你的子视图。 ItemsControl允许您使用DataTemplateSelector。因此,根据您的枚举值,您可以生成一些输出,选择器可以使用它来确定要使用的数据模板。尝试对选择器进行一些研究。如果您仍然感到困惑,请随时与我联系。祝好运。
答案 1 :(得分:0)
对于动画,我建议一个容纳你的子视图的容器控件。查看this link以获得一个非常可靠的实现,以帮助您入门。