|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:winInter="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:hwpf="clr-namespace:HurWpfLib">
<BooleanToVisibilityConverter x:Key="boolVisConverter"/>
<hwpf:DoubleGridLengthConverter x:Key="splitPositionConverter"/>
<!--The style which is applied to an unsplit view's inner border-->
<Style x:Key="DefaultUnsplitBorderStyle" TargetType="Border">
<Style.Setters>
<Setter Property="Background" Value="LightBlue"/>
<Setter Property="CornerRadius" Value="0"/>
</Style.Setters>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected}" Value="False">
<Setter Property="BorderBrush" Value="RoyalBlue"/>
<Setter Property="BorderThickness" Value="1"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsSelected}" Value="True">
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="BorderThickness" Value="2"/>
</DataTrigger>
</Style.Triggers>
</Style>
<sys:Boolean x:Key="trueValue">True</sys:Boolean>
<DataTemplate x:Key="UnsplitTemplate">
<!--The elements in this template will appear in the content template of the styled ContentControl.
Therefore, they make use of the content as their DataContext.-->
<Border x:Name="viewBorder" Style="{StaticResource DefaultUnsplitBorderStyle}">
<ContentPresenter x:Name="innerContentPresenter" Content="{Binding Path=InnerContent}"
ContentTemplateSelector="{x:Static hwpf:RecursiveSplitViewModel.InnerContentTemplateSelector}">
</ContentPresenter>
<!--This should help an unsplit view to get its viewmodel selected if clicked or became the target of a drop action.-->
<winInter:Interaction.Triggers>
<winInter:EventTrigger EventName="PreviewMouseDown">
<winInter:InvokeCommandAction Command="{Binding Path=SelectCommand, Mode=OneWay}" CommandParameter="{StaticResource trueValue}"/>
</winInter:EventTrigger>
<winInter:EventTrigger EventName="PreviewDrop">
<winInter:InvokeCommandAction Command="{Binding Path=SelectCommand, Mode=OneWay}" CommandParameter="{StaticResource trueValue}"/>
</winInter:EventTrigger>
</winInter:Interaction.Triggers>
</Border>
</DataTemplate>
<DataTemplate x:Key="HorizontalSplitTemplate">
<!--The elements in this template will appear in the content template of the styled ContentControl.
Therefore, they make use of the content as their DataContext.-->
<Grid x:Name="splitViewGrid">
<Grid.RowDefinitions>
<!--The top panel height is bound to the SplitPosition property.
I would love to be able to express SplitPosition as a fractional value (ranging from 0 to 1),
but I just wasn't able to use the control size as a ConverterParameter.-->
<RowDefinition Height="{Binding Path=SplitPosition, Mode=TwoWay, Converter={StaticResource splitPositionConverter}}"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--The splittable view associated with Child1 viewmodel object-->
<ContentControl Grid.Row="0" Style="{DynamicResource RecursiveSplitViewStyle}"
DataContext="{Binding Path=Child1}" x:Name="child1View"/>
<!--The grid splitter object separating the child views.-->
<GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ResizeDirection="Rows"
Height="{Binding Source={x:Static hwpf:RecursiveSplitViewModel.DefaultSplitterWidth}}"/>
<!--The splittable view associated with Child2 viewmodel object-->
<ContentControl Grid.Row="2" Style="{DynamicResource RecursiveSplitViewStyle}"
DataContext="{Binding Path=Child2}" x:Name="child2View"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="VerticalSplitTemplate">
<!--The elements in this template will appear in the content template of the styled ContentControl.
Therefore, they make use of the content as their DataContext.-->
<Grid x:Name="splitViewGrid">
<Grid.ColumnDefinitions>
<!--The left panel width is bound to the SplitPosition property.
I would love to be able to express SplitPosition as a fractional value (ranging from 0 to 1),
but I just wasn't able to use the control size as a ConverterParameter.-->
<ColumnDefinition Width="{Binding Path=SplitPosition, Mode=TwoWay, Converter={StaticResource splitPositionConverter}}"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!--The splittable view associated with Child1 viewmodel object-->
<ContentControl Grid.Column="0" Style="{DynamicResource RecursiveSplitViewStyle}"
DataContext="{Binding Path=Child1}" x:Name="child1View"/>
<!--The grid splitter object separating the child views.-->
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ResizeDirection="Columns"
Width="{Binding Source={x:Static hwpf:RecursiveSplitViewModel.DefaultSplitterWidth}}"/>
<!--The splittable view associated with Child2 viewmodel object-->
<ContentControl Grid.Column="2" Style="{DynamicResource RecursiveSplitViewStyle}"
DataContext="{Binding Path=Child2}" x:Name="child2View"/>
</Grid>
</DataTemplate>
<!--I learned about pass enum values as parameters from http://social.msdn.microsoft.com/forums/en-US/wpf/thread/03e543f8-c8f5-4a1c-9348-91200c9c1091/-->
<ContextMenu x:Key="splitViewContextMenu" x:Shared="True" x:Name="splitViewContextMenu">
<MenuItem Header="Horizontal Split" Command="{Binding Path=SplitCommand}" CommandParameter="{x:Static hwpf:RecursiveSplitState.HorizontalSplit}"/>
<MenuItem Header="Vertical Split" Command="{Binding Path=SplitCommand}" CommandParameter="{x:Static hwpf:RecursiveSplitState.VerticalSplit}"/>
</ContextMenu>
<!--A ContentControl with this style will have a RecursiveSplitViewModel object as its DataContext.
It will also have this object as its Content, so that the elements in its current ContentTemplate
will use it as their DataContext, as well.-->
<Style x:Key="RecursiveSplitViewStyle" TargetType="{x:Type ContentControl}">
<Style.Setters>
<Setter Property="AllowDrop" Value="{Binding Path=IsEnabled}"/>
<Setter Property="Content" Value="{Binding}"/>
</Style.Setters>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=SplitState}" Value="Unsplit">
<Setter Property="ContentTemplate" Value="{StaticResource UnsplitTemplate}"/>
<Setter Property="ContextMenu" Value="{StaticResource splitViewContextMenu}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=SplitState}" Value="HorizontalSplit">
<Setter Property="ContentTemplate" Value="{StaticResource HorizontalSplitTemplate}"/>
<Setter Property="ContextMenu" Value="{x:Null}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=SplitState}" Value="VerticalSplit">
<Setter Property="ContentTemplate" Value="{StaticResource VerticalSplitTemplate}"/>
<Setter Property="ContextMenu" Value="{x:Null}"/>
</DataTrigger>
</Style.Triggers>
</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.
A Physics PhD with an engineering background who also earned an MBA. I am a long-time programmer who was confined to coding for academic purposes. Since 2004, I have been extending my coding skills into wider areas, like desktop interface development with data binding, automation of office applications, and development of physics simulations targeting social phenomena.