Předchozí díly:
- MVVM #1–Úvod
- MVVM #2–Příprava
- MVVM #3–Shell
V minulých dílech jsme si připravili téměř vše podstatné až na hlavní View. To bude předmětem dnešního dílu, kde si kromě vytvoření samotného View ukážeme, jak využít “Design Data” v době návrhu. Aby jsme si tedy mohli otestovat, že náš layout bude odpovídat skutečně tomu co jsme chtěli.
<Window x:Class="MVVMSample.Shell.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="768" Width="1024">
<Grid Background="#ffeeeeee">
<Grid.Resources>
<Style x:Key="GroupCommandsTemplate" TargetType="{x:Type ItemsControl}">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Button Content="{Binding Name}"
Command="{Binding}"
BorderThickness="0"
FontWeight="Normal"
HorizontalContentAlignment="Left"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="ClosableTabItemTemplate">
<DockPanel Width="120">
<Button Command="{Binding CloseCommand}"
Content="X"
DockPanel.Dock="Right"
Width="16" Height="16" />
<ContentPresenter Content="{Binding DisplayName}" />
</DockPanel>
</DataTemplate>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="170"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Navigacni menu - GroupCommands -->
<ScrollViewer Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="0"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding GroupCommands}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander Header="{Binding GroupName}"
IsExpanded="True"
Foreground="#FF97D045"
Margin="5,0,0,0"
FontWeight="Bold">
<ItemsControl ItemsSource="{Binding Commands}"
Style="{StaticResource GroupCommandsTemplate}"
HorizontalContentAlignment="Stretch"
Margin="22,0,10,12"
BorderThickness="0.0"/>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!-- Pracovni prostor -->
<Grid Grid.Row="0"
Grid.Column="1"
Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Ovladaci tlacitka obsahu - Action Commands -->
<ScrollViewer HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding SelectedWorkspaceCommands}"
Background="#ff888888"
BorderBrush="Black"
BorderThickness="1,0,1,0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="{Binding}"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Width="80"
Height="40"
Margin="0,5,0,0"
Content="{Binding Name}">
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!-- Finalni obsah - SelectedWorkspace -->
<TabControl ItemsSource="{Binding Workspaces}"
Grid.Column="1"
SelectedItem="{Binding SelectedWorkspace, Mode=TwoWay}"
ItemTemplate="{StaticResource ClosableTabItemTemplate}"/>
</Grid>
</Grid>
</Window>
XAML vypadá ve výsledku takhle:

Hmm to nám toho moc neřekne, tak pojďmě si vytvořit nějaký model, který budeme moct použit už při návrhu a uvidíme, zda jsme všechny styly a bindingy nastavili správně.
Pro tuto demonstraci si vytvoříme třídu DesignMainWindowViewModel, který bude dědit ze třídy MainWindowViewModel a DesignWorkspaceViewModel, která bude dědit ze třídy WorkspaceViewModel. Jediné co DesignMainWindowViewModel udělá je, že v konstruktoru naplní potřebné vlastnosti GroupCommands, Workspaces a SelectedWorkspace.
DesignWorkspaceViewModel
namespace MVVMSample.ViewModels
{
internal class DesignWorkspaceViewModel : WorkspaceViewModel
{
public DesignWorkspaceViewModel()
{
}
public DesignWorkspaceViewModel(string displayName)
{
DisplayName = displayName;
}
}
}
DesignWorkspaceViewModel
using System.Collections.Generic;
using MVVMSample.Commands;
using System.Windows;
namespace MVVMSample.ViewModels
{
internal class DesignMainWindowViewModel : MainWindowViewModel
{
public DesignMainWindowViewModel()
{
GroupCommand moduleA = new GroupCommand()
{
GroupName = Shared.Strings.GroupCommand_ModuleA,
Commands = new List< RelayCommand >()
{
new UICommand(
execute =>
MessageBox.Show(Shared.Strings.Command_ViewModelA1))
{
Name = Shared.Strings.Command_ViewModelA1
},
new UICommand(
execute =>
MessageBox.Show(Shared.Strings.Command_ViewModelA2))
{
Name = Shared.Strings.Command_ViewModelA2
},
new UICommand(
execute =>
MessageBox.Show(Shared.Strings.Command_ViewModelA3))
{
Name = Shared.Strings.Command_ViewModelA3
}
}
};
GroupCommand moduleB = new GroupCommand()
{
GroupName = Shared.Strings.GroupCommand_ModuleB,
Commands = new List< RelayCommand >()
{
new UICommand(
execute =>
MessageBox.Show(Shared.Strings.Command_ViewModelB1))
{
Name = Shared.Strings.Command_ViewModelB1
}
}
};
GroupCommand moduleC = new GroupCommand()
{
GroupName = Shared.Strings.GroupCommand_ModuleC,
Commands = new List< RelayCommand >()
{
new UICommand(
execute =>
MessageBox.Show(Shared.Strings.Command_ViewModelC1))
{
Name = Shared.Strings.Command_ViewModelC1
}
}
};
GroupCommands = new List< GroupCommand >()
{
moduleA,moduleB,moduleC
};
Workspaces.Add(new DesignWorkspaceViewModel("ViewModelA1"));
Workspaces.Add(new DesignWorkspaceViewModel("ViewModelA2"));
SelectedWorkspace = Workspaces[0];
}
}
}
Pokud tohle uděláme, můžeme dostat už v době návrhu docela dobrý feedback o našem návrhu.

Kromě vytvoření zmiňovaných tříd je zapotřebí v definici XAMLu nastavit, že se jako DataContext má nastavit právě náš DesignMainWindowViewModel
d:DataContext="{d:DesignInstance vm:DesignMainWindowViewModel, IsDesignTimeCreatable=True}"
Příště si už vytvoříme nějaký modul a ukážeme jak nastavit aby se pro ViewModel A zobrazilo View A apod.