Click here to Skip to main content
Click here to Skip to main content
 
Add your own
alternative version
Go to top

Presentation Model (MVVM) Good Practices

, 11 May 2010
Showing some good practices that can be applied to the Presentation Model/MVVM pattern.
PresentationModelDemo.zip
App.Configuration
App.Configuration.Wpf
Interceptors
Properties
Wpf
Properties
Wpf
App.Core
Model
PresentationModel
Properties
Services
App.Data
Properties
libs
AttachedCommandBehavior.dll
Castle.Core.dll
Castle.DynamicProxy2.dll
Castle.MicroKernel.dll
Castle.Windsor.dll
PresentationModelBase
Properties
WPFUI
Properties
Settings.settings
View
<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:acb="clr-namespace:AttachedCommandBehavior;assembly=AttachedCommandBehavior"
    xmlns:pm="clr-namespace:App.Core;assembly=App.Core"
    xmlns:vw="clr-namespace:WPFUI.View"
    >
    <DataTemplate x:Key="DataGridHeaderTemplate">
        <TextBlock Text="{Binding}" Foreground="Black"/>
    </DataTemplate>

    <DataTemplate DataType="{x:Type pm:ProductEditViewPresentationModel}">
        <vw:ProductEditView/>
    </DataTemplate>
    
    <DataTemplate DataType="{x:Type pm:ProductsViewPresentationModel}">
        <vw:ProductsView/>
    </DataTemplate>

    
    <Style
        x:Key="EntityListViewItemStyle"
        TargetType="{x:Type ListViewItem}"
        BasedOn="{StaticResource {x:Type ListViewItem}}"
        >
        <Setter Property="acb:CommandBehavior.Command" Value="{Binding Call}"/>
        <Setter Property="acb:CommandBehavior.CommandParameter" Value="OpenEditView"/>
        <Setter Property="acb:CommandBehavior.Event" Value="MouseDoubleClick"/>                 
    </Style>
    
    <Style
        x:Key="EntityCollectionViewListStyle"
        TargetType="{x:Type ListView}"
        BasedOn="{StaticResource {x:Type ListView}}"
        >
        <Setter Property="ItemContainerStyle" Value="{StaticResource EntityListViewItemStyle}"/>
        <Setter Property="SelectionMode" Value="Single"/>
        <Setter Property="SelectedItem" Value="{Binding Selected}"/>        
    </Style>
        
        
    <Style 
        x:Key="ViewStyle"
        TargetType="{x:Type UserControl}"
        BasedOn="{StaticResource {x:Type UserControl}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type UserControl}">
                    <Grid
                        Background="{TemplateBinding Background}">
                        <ContentPresenter
                            x:Name="MainContent"                   
                            Content="{TemplateBinding Content}"                                    
                            >
                        </ContentPresenter>
                        <Border
                            x:Name="WorkingPanel"                            
                            Background="White"
                            Opacity="0.4"
                            CornerRadius="5"
                            Panel.ZIndex="5"
                            Height="{TemplateBinding ActualHeight}"
                            Width="{TemplateBinding ActualWidth}"
                            Visibility="Hidden"
                            >
                            <TextBlock 
                                x:Name="WorkingText"
                                VerticalAlignment="Center"
                                HorizontalAlignment="Center"
                                FontSize="16"
                                FontWeight="Bold"
                                Text="Working..."
                                Foreground="Black"
                                >
                            </TextBlock>
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <DataTrigger
                            Binding="{Binding IsWorking}"
                            Value="True"
                            >
                            <Setter
                                TargetName="MainContent"
                                Property="IsEnabled"
                                Value="False"
                                />
                            <Setter
                                TargetName="WorkingPanel"
                                Property="Visibility"
                                Value="Visible"
                                />
                            <DataTrigger.EnterActions>
                                <BeginStoryboard
                                    Name="StartWorking"
                                    >
                                    <Storyboard>
                                        <DoubleAnimation
                                            Storyboard.TargetName="WorkingText"
                                            Storyboard.TargetProperty="Opacity"
                                            AutoReverse="True"
                                            Duration="0:0:0.5"
                                            From="1"
                                            To="0.2"
                                            RepeatBehavior="Forever"
                                            />
                                    </Storyboard>
                                </BeginStoryboard>
                            </DataTrigger.EnterActions>
                            <DataTrigger.ExitActions>
                                <StopStoryboard BeginStoryboardName="StartWorking" />
                            </DataTrigger.ExitActions>
                        </DataTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style
        TargetType="{x:Type TextBlock}"
        BasedOn="{StaticResource {x:Type TextBlock}}">
        <Setter 
            Property="Foreground"
            Value="White"
            />            
    </Style>
    
    <SolidColorBrush x:Key="ApplicationBackgroundBrush" Color="Transparent"/>

    <DataTemplate x:Key="ClosableTabItemTemplate">
        <DockPanel>
            <Button            
                    Content="X"                    
                    Command="{Binding Call}"
                    CommandParameter="Close"
                    Cursor="Hand"                    
                    DockPanel.Dock="Right"
                    Focusable="False"
                    FontFamily="Courier"
                    FontSize="9"
                    FontWeight="Bold"                    
                    Margin="10,0,0,0"
                    VerticalContentAlignment="Bottom"
                    Height="18">
                <Button.Style>
                    <Style
                        TargetType="{x:Type Button}"
                        BasedOn="{StaticResource {x:Type Button}}">
                        <Style.Triggers>
                            <DataTrigger
                                Binding="{Binding IsWorking}"
                                Value="True"
                                >
                                <Setter 
                                    Property="IsEnabled"
                                    Value="False"
                                    />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </Button.Style>
            </Button>  
            <TextBlock 
                Text="{Binding DisplayName}"
                VerticalAlignment="Center">
                <TextBlock.Style>
                  <Style
                      TargetType="{x:Type TextBlock}">
                      <Style.Triggers>
                          <DataTrigger
                              Binding="{Binding IsSelected}"
                              Value="True">
                              <Setter
                                  Property="Foreground"
                                  Value="Black"
                                  />
                          </DataTrigger>
                      </Style.Triggers>
                  </Style>
                </TextBlock.Style>
            </TextBlock>
        </DockPanel>
    </DataTemplate>

    <Style
            x:Key="WorkspaceTabItemStyle"
            TargetType="{x:Type TabItem}"
            BasedOn="{StaticResource {x:Type TabItem}}"
            >
        <Setter 
                Property="Background"
                Value="{StaticResource ApplicationBackgroundBrush}"
                />
        <Setter
                Property="ToolTip"
                Value="{Binding DisplayName}"
                />
        <Setter
                Property="IsSelected"
                Value="{Binding IsSelected}"
                />
    </Style>

    <Style 
            x:Key="WorkspaceTabControlStyle"
            TargetType="{x:Type TabControl}"
            BasedOn="{StaticResource {x:Type TabControl}}"
            >
        <Setter
                Property="ItemContainerStyle"
                Value="{StaticResource WorkspaceTabItemStyle}"
                />
        <Style.Triggers>
            <DataTrigger 
                    Binding="{Binding RelativeSource={RelativeSource Self}, Path=Items.Count}" 
                    Value="0">
                <Setter Property="Visibility" Value="Hidden" />
            </DataTrigger>
        </Style.Triggers>
    </Style>

    <DataTemplate x:Key="WorkspacesTemplate">
        <TabControl
                Background="{StaticResource ApplicationBackgroundBrush}"
                ItemsSource="{Binding}"
                ItemTemplate="{StaticResource ClosableTabItemTemplate}"
                Margin="4"
                Style="{StaticResource WorkspaceTabControlStyle}"/>
    </DataTemplate>

    <DataTemplate x:Key="NavigationMenuTemplate">
        <ItemsControl 
                IsTabStop="False"
                ItemsSource="{Binding}" 
                Margin="6,2">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button 
                            Content="{Binding DisplayName}"
                            Command="{Binding Call}"
                            CommandParameter="ExecuteAction"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </DataTemplate>   

    <Style x:Key="MainHCCStyle" TargetType="{x:Type HeaderedContentControl}">
        <Setter Property="HeaderTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Border 
                            BorderBrush="LightGray" 
                            BorderThickness="1"  
                            CornerRadius="2"
                            Margin="4" 
                            Padding="4" 
                            SnapsToDevicePixels="True">
                        <TextBlock 
                                FontSize="14"
                                FontWeight="Bold"                                
                                HorizontalAlignment="Center"
                                Text="{TemplateBinding Content}"/>
                    </Border>
                </DataTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="IsTabStop" Value="False" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type HeaderedContentControl}">
                    <DockPanel>
                        <ContentPresenter 
                                DockPanel.Dock="Top"
                                ContentSource="Header"
                                ContentTemplate="{TemplateBinding HeaderTemplate}"/>
                        <ContentPresenter 
                                ContentSource="Content"
                                ContentTemplate="{TemplateBinding ContentTemplate}"/>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Software developer specialized in the .NET framework

| Advertise | Privacy | Mobile
Web01 | 2.8.140921.1 | Last Updated 11 May 2010
Article Copyright 2010 by Thiago de Arruda
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid