浏览代码

Added ability to have Left and Right Panels in DynamicTabControl

frogsoftware 1 年之前
父节点
当前提交
01c41b0410
共有 3 个文件被更改,包括 221 次插入128 次删除
  1. 18 0
      inabox.wpf/DynamicGrid/DynamicTabControl.cs
  2. 26 0
      inabox.wpf/Themes/Generic.cs
  3. 177 128
      inabox.wpf/Themes/Generic.xaml

+ 18 - 0
inabox.wpf/DynamicGrid/DynamicTabControl.cs

@@ -79,6 +79,24 @@ namespace InABox.DynamicGrid
             get => (bool)GetValue(CanCreateTabProperty);
             set => SetValue(CanCreateTabProperty, value);
         }
+        
+        public static readonly DependencyProperty LeftPanelProperty =
+            DependencyProperty.Register(nameof(LeftPanel), typeof(FrameworkElement), typeof(DynamicTabControl), new UIPropertyMetadata(null));
+        
+        public FrameworkElement LeftPanel
+        {
+            get => (FrameworkElement)GetValue(LeftPanelProperty);
+            set => SetValue(LeftPanelProperty, value);
+        }
+        
+        public static readonly DependencyProperty RightPanelProperty =
+            DependencyProperty.Register(nameof(RightPanel), typeof(FrameworkElement), typeof(DynamicTabControl), new UIPropertyMetadata(null));
+        
+        public FrameworkElement RightPanel
+        {
+            get => (FrameworkElement)GetValue(RightPanelProperty);
+            set => SetValue(RightPanelProperty, value);
+        }
 
         public DynamicTabItem? SelectedTab => (SelectedItem as DynamicTabItem)!;
         

+ 26 - 0
inabox.wpf/Themes/Generic.cs

@@ -10,6 +10,32 @@ using System.Windows.Input;
 
 namespace InABox.WPF
 {
+    public class ObjectToGridLengthConverter : UtilityConverter<FrameworkElement?, GridLength>
+    {
+        public GridLength NotNull { get; set; } = new GridLength(0, GridUnitType.Pixel);
+        public GridLength IsNull { get; set; } = new GridLength(1, GridUnitType.Auto);
+        
+        public override GridLength Convert(FrameworkElement? value)
+        {
+            return value == null
+                ? IsNull
+                : NotNull;
+        }
+    }
+    
+    public class ObjectToVisibilityConverter : UtilityConverter<FrameworkElement?, Visibility>
+    {
+        public Visibility NotNull { get; set; } = Visibility.Visible;
+        public Visibility IsNull { get; set; } = Visibility.Collapsed;
+        
+        public override Visibility Convert(FrameworkElement? value)
+        {
+            return value == null
+                ? IsNull
+                : NotNull;
+        }
+    }  
+    
     public partial class Generic : ResourceDictionary
     {
         public Generic()

+ 177 - 128
inabox.wpf/Themes/Generic.xaml

@@ -7,6 +7,8 @@
     xmlns:themes="clr-namespace:InABox.WPF.Themes"
     x:Class="InABox.WPF.Generic"
     x:ClassModifier="public">
+    
+    <wpf:ObjectToVisibilityConverter x:Key="DynamicTabControlVisibilityConverter" IsNull="Collapsed" NotNull="Visible" />
 
     <!-- VerticalSplitter -->
     <ControlTemplate x:Key="VerticalSplitter">
@@ -414,132 +416,132 @@
         </Setter>
     </Style>
 
-               <ControlTemplate x:Key="VerticalColumnHeader"
-                     TargetType="{x:Type syncfusion:GridHeaderCellControl}">
-                <Grid>
-                    <Grid.LayoutTransform>
-                        <RotateTransform Angle="270" />
-                    </Grid.LayoutTransform>
-                    <VisualStateManager.VisualStateGroups>
-                        <VisualStateGroup x:Name="HiddenColumnsResizingStates">
-                            <VisualState x:Name="PreviousColumnHidden">
-                                <Storyboard>
-                                    <ThicknessAnimationUsingKeyFrames BeginTime="0" Duration="1.0:0:0"
-                                                                      Storyboard.TargetProperty="BorderThickness"
-                                                                      Storyboard.TargetName="PART_HeaderCellBorder">
-                                        <EasingThicknessKeyFrame KeyTime="0" Value="3,0,1,1" />
-                                    </ThicknessAnimationUsingKeyFrames>
-                                </Storyboard>
-                            </VisualState>
-                            <VisualState x:Name="HiddenState">
-                                <Storyboard>
-                                    <ThicknessAnimationUsingKeyFrames BeginTime="0" Duration="1.0:0:0"
-                                                                      Storyboard.TargetProperty="BorderThickness"
-                                                                      Storyboard.TargetName="PART_HeaderCellBorder">
-                                        <EasingThicknessKeyFrame KeyTime="0" Value="3,0,3,1" />
-                                    </ThicknessAnimationUsingKeyFrames>
-                                </Storyboard>
-                            </VisualState>
-                            <VisualState x:Name="NormalState" />
-                            <VisualState x:Name="LastColumnHidden">
-                                <Storyboard>
-                                    <ThicknessAnimationUsingKeyFrames BeginTime="0" Duration="1.0:0:0"
-                                                                      Storyboard.TargetProperty="BorderThickness"
-                                                                      Storyboard.TargetName="PART_HeaderCellBorder">
-                                        <EasingThicknessKeyFrame KeyTime="0" Value="0,0,3,1" />
-                                    </ThicknessAnimationUsingKeyFrames>
-                                </Storyboard>
-                            </VisualState>
-                        </VisualStateGroup>
-                        <VisualStateGroup x:Name="CommonStates">
-                            <VisualState x:Name="MouseOver" />
-                            <VisualState x:Name="Normal" />
-                        </VisualStateGroup>
-                        <VisualStateGroup x:Name="BorderStates">
-                            <VisualState x:Name="NormalCell" />
-                            <VisualState x:Name="FooterColumnCell">
-                                <Storyboard BeginTime="0">
-                                    <ThicknessAnimationUsingKeyFrames BeginTime="0" Duration="1.0:0:0"
-                                                                      Storyboard.TargetProperty="BorderThickness"
-                                                                      Storyboard.TargetName="PART_FooterCellBorder">
-                                        <EasingThicknessKeyFrame KeyTime="0" Value="1,0,1,1" />
-                                    </ThicknessAnimationUsingKeyFrames>
-                                </Storyboard>
-                            </VisualState>
-                            <VisualState x:Name="BeforeFooterColumnCell">
-                                <Storyboard BeginTime="0">
-                                    <ThicknessAnimationUsingKeyFrames BeginTime="0" Duration="1.0:0:0"
-                                                                      Storyboard.TargetProperty="BorderThickness"
-                                                                      Storyboard.TargetName="PART_FooterCellBorder">
-                                        <EasingThicknessKeyFrame KeyTime="0" Value="0,0,0,1" />
-                                    </ThicknessAnimationUsingKeyFrames>
-                                    <ThicknessAnimationUsingKeyFrames BeginTime="0" Duration="1.0:0:0"
-                                                                      Storyboard.TargetProperty="BorderThickness"
-                                                                      Storyboard.TargetName="PART_HeaderCellBorder">
-                                        <EasingThicknessKeyFrame KeyTime="0" Value="0,0,0,1" />
-                                    </ThicknessAnimationUsingKeyFrames>
-                                </Storyboard>
-                            </VisualState>
-                        </VisualStateGroup>
-                    </VisualStateManager.VisualStateGroups>
-                    <Border x:Name="PART_FooterCellBorder" BorderBrush="{TemplateBinding BorderBrush}"
-                            Background="{TemplateBinding Background}" />
-                    <Border x:Name="PART_HeaderCellBorder" BorderBrush="{TemplateBinding BorderBrush}"
-                            BorderThickness="{TemplateBinding BorderThickness}"
-                            Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
-                        <Grid Margin="{TemplateBinding Padding}" SnapsToDevicePixels="True">
-                            <Grid.ColumnDefinitions>
-                                <ColumnDefinition Width="*" />
-                                <ColumnDefinition Width="Auto" />
-                                <ColumnDefinition Width="Auto" />
-                            </Grid.ColumnDefinitions>
-                            <ContentPresenter
-                                ContentTemplate="{TemplateBinding ContentTemplate}"
-                                ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False"
-                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
-                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
-                                <ContentPresenter.Content>
-                                    <TextBlock Text="{Binding HeaderText}" TextWrapping="Wrap" />
-                                </ContentPresenter.Content>
-                            </ContentPresenter>
-                            <Grid x:Name="PART_SortButtonPresenter" Grid.Column="1" SnapsToDevicePixels="True">
-                                <Grid.ColumnDefinitions>
-                                    <ColumnDefinition Width="*">
-                                        <ColumnDefinition.MinWidth>
-                                            <Binding Mode="OneWay" Path="SortDirection"
-                                                     RelativeSource="{RelativeSource TemplatedParent}">
-                                                <Binding.Converter>
-                                                    <syncfusion:SortDirectionToWidthConverter />
-                                                </Binding.Converter>
-                                            </Binding>
-                                        </ColumnDefinition.MinWidth>
-                                    </ColumnDefinition>
-                                    <ColumnDefinition Width="*" />
-                                </Grid.ColumnDefinitions>
-                                <TextBlock Grid.Column="1" Foreground="{TemplateBinding Foreground}"
-                                           FontSize="10" Margin="0,-4,0,0" SnapsToDevicePixels="True"
-                                           Text="{TemplateBinding SortNumber}"
-                                           Visibility="{TemplateBinding SortNumberVisibility}"
-                                           VerticalAlignment="Bottom" />
-                            </Grid>
-                            <syncfusion:FilterToggleButton x:Name="PART_FilterToggleButton" Grid.Column="2"
-                                                           HorizontalAlignment="Stretch"
-                                                           SnapsToDevicePixels="True"
-                                                           Visibility="{TemplateBinding FilterIconVisiblity}"
-                                                           VerticalAlignment="Stretch">
-                                <syncfusion:FilterToggleButton.LayoutTransform>
-                                    <RotateTransform Angle="90" />
-                                </syncfusion:FilterToggleButton.LayoutTransform>
-                            </syncfusion:FilterToggleButton>
-                            <Border x:Name="PART_FilterPopUpPresenter">
-                                <Border.LayoutTransform>
-                                    <RotateTransform Angle="90" />
-                                </Border.LayoutTransform>
-                            </Border>
-                        </Grid>
+    <ControlTemplate x:Key="VerticalColumnHeader"
+         TargetType="{x:Type syncfusion:GridHeaderCellControl}">
+        <Grid>
+            <Grid.LayoutTransform>
+                <RotateTransform Angle="270" />
+            </Grid.LayoutTransform>
+            <VisualStateManager.VisualStateGroups>
+                <VisualStateGroup x:Name="HiddenColumnsResizingStates">
+                    <VisualState x:Name="PreviousColumnHidden">
+                        <Storyboard>
+                            <ThicknessAnimationUsingKeyFrames BeginTime="0" Duration="1.0:0:0"
+                                                              Storyboard.TargetProperty="BorderThickness"
+                                                              Storyboard.TargetName="PART_HeaderCellBorder">
+                                <EasingThicknessKeyFrame KeyTime="0" Value="3,0,1,1" />
+                            </ThicknessAnimationUsingKeyFrames>
+                        </Storyboard>
+                    </VisualState>
+                    <VisualState x:Name="HiddenState">
+                        <Storyboard>
+                            <ThicknessAnimationUsingKeyFrames BeginTime="0" Duration="1.0:0:0"
+                                                              Storyboard.TargetProperty="BorderThickness"
+                                                              Storyboard.TargetName="PART_HeaderCellBorder">
+                                <EasingThicknessKeyFrame KeyTime="0" Value="3,0,3,1" />
+                            </ThicknessAnimationUsingKeyFrames>
+                        </Storyboard>
+                    </VisualState>
+                    <VisualState x:Name="NormalState" />
+                    <VisualState x:Name="LastColumnHidden">
+                        <Storyboard>
+                            <ThicknessAnimationUsingKeyFrames BeginTime="0" Duration="1.0:0:0"
+                                                              Storyboard.TargetProperty="BorderThickness"
+                                                              Storyboard.TargetName="PART_HeaderCellBorder">
+                                <EasingThicknessKeyFrame KeyTime="0" Value="0,0,3,1" />
+                            </ThicknessAnimationUsingKeyFrames>
+                        </Storyboard>
+                    </VisualState>
+                </VisualStateGroup>
+                <VisualStateGroup x:Name="CommonStates">
+                    <VisualState x:Name="MouseOver" />
+                    <VisualState x:Name="Normal" />
+                </VisualStateGroup>
+                <VisualStateGroup x:Name="BorderStates">
+                    <VisualState x:Name="NormalCell" />
+                    <VisualState x:Name="FooterColumnCell">
+                        <Storyboard BeginTime="0">
+                            <ThicknessAnimationUsingKeyFrames BeginTime="0" Duration="1.0:0:0"
+                                                              Storyboard.TargetProperty="BorderThickness"
+                                                              Storyboard.TargetName="PART_FooterCellBorder">
+                                <EasingThicknessKeyFrame KeyTime="0" Value="1,0,1,1" />
+                            </ThicknessAnimationUsingKeyFrames>
+                        </Storyboard>
+                    </VisualState>
+                    <VisualState x:Name="BeforeFooterColumnCell">
+                        <Storyboard BeginTime="0">
+                            <ThicknessAnimationUsingKeyFrames BeginTime="0" Duration="1.0:0:0"
+                                                              Storyboard.TargetProperty="BorderThickness"
+                                                              Storyboard.TargetName="PART_FooterCellBorder">
+                                <EasingThicknessKeyFrame KeyTime="0" Value="0,0,0,1" />
+                            </ThicknessAnimationUsingKeyFrames>
+                            <ThicknessAnimationUsingKeyFrames BeginTime="0" Duration="1.0:0:0"
+                                                              Storyboard.TargetProperty="BorderThickness"
+                                                              Storyboard.TargetName="PART_HeaderCellBorder">
+                                <EasingThicknessKeyFrame KeyTime="0" Value="0,0,0,1" />
+                            </ThicknessAnimationUsingKeyFrames>
+                        </Storyboard>
+                    </VisualState>
+                </VisualStateGroup>
+            </VisualStateManager.VisualStateGroups>
+            <Border x:Name="PART_FooterCellBorder" BorderBrush="{TemplateBinding BorderBrush}"
+                    Background="{TemplateBinding Background}" />
+            <Border x:Name="PART_HeaderCellBorder" BorderBrush="{TemplateBinding BorderBrush}"
+                    BorderThickness="{TemplateBinding BorderThickness}"
+                    Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
+                <Grid Margin="{TemplateBinding Padding}" SnapsToDevicePixels="True">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="*" />
+                        <ColumnDefinition Width="Auto" />
+                        <ColumnDefinition Width="Auto" />
+                    </Grid.ColumnDefinitions>
+                    <ContentPresenter
+                        ContentTemplate="{TemplateBinding ContentTemplate}"
+                        ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False"
+                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
+                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
+                        <ContentPresenter.Content>
+                            <TextBlock Text="{Binding HeaderText}" TextWrapping="Wrap" />
+                        </ContentPresenter.Content>
+                    </ContentPresenter>
+                    <Grid x:Name="PART_SortButtonPresenter" Grid.Column="1" SnapsToDevicePixels="True">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="*">
+                                <ColumnDefinition.MinWidth>
+                                    <Binding Mode="OneWay" Path="SortDirection"
+                                             RelativeSource="{RelativeSource TemplatedParent}">
+                                        <Binding.Converter>
+                                            <syncfusion:SortDirectionToWidthConverter />
+                                        </Binding.Converter>
+                                    </Binding>
+                                </ColumnDefinition.MinWidth>
+                            </ColumnDefinition>
+                            <ColumnDefinition Width="*" />
+                        </Grid.ColumnDefinitions>
+                        <TextBlock Grid.Column="1" Foreground="{TemplateBinding Foreground}"
+                                   FontSize="10" Margin="0,-4,0,0" SnapsToDevicePixels="True"
+                                   Text="{TemplateBinding SortNumber}"
+                                   Visibility="{TemplateBinding SortNumberVisibility}"
+                                   VerticalAlignment="Bottom" />
+                    </Grid>
+                    <syncfusion:FilterToggleButton x:Name="PART_FilterToggleButton" Grid.Column="2"
+                                                   HorizontalAlignment="Stretch"
+                                                   SnapsToDevicePixels="True"
+                                                   Visibility="{TemplateBinding FilterIconVisiblity}"
+                                                   VerticalAlignment="Stretch">
+                        <syncfusion:FilterToggleButton.LayoutTransform>
+                            <RotateTransform Angle="90" />
+                        </syncfusion:FilterToggleButton.LayoutTransform>
+                    </syncfusion:FilterToggleButton>
+                    <Border x:Name="PART_FilterPopUpPresenter">
+                        <Border.LayoutTransform>
+                            <RotateTransform Angle="90" />
+                        </Border.LayoutTransform>
                     </Border>
                 </Grid>
-            </ControlTemplate>
+            </Border>
+        </Grid>
+    </ControlTemplate>
     
     
     <Style BasedOn="{StaticResource {x:Type TabItem}}" TargetType="{x:Type local:DynamicTabItem}">
@@ -624,17 +626,29 @@
     <!-- </DataTemplate> -->
 
     <Style BasedOn="{StaticResource {x:Type TabControl}}" TargetType="{x:Type local:DynamicTabControl}">
-
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="{x:Type local:DynamicTabControl}">
-                    <Grid Background="Transparent">
+                    <Grid Background="Transparent" Margin="0,0,0,0">
                         <Grid.RowDefinitions>
                             <RowDefinition Height="Auto" />
                             <RowDefinition Height="*" />
                             <RowDefinition Height="Auto" />
                         </Grid.RowDefinitions>
-                        <Border x:Name="Separator" BorderBrush="Gray">
+                        
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto"/>
+                            <ColumnDefinition Width="Auto"/>
+                            <ColumnDefinition Width="*"/>
+                            <ColumnDefinition Width="Auto"/>
+                            <ColumnDefinition Width="Auto"/>
+                        </Grid.ColumnDefinitions>
+                        
+                        <Border 
+                            x:Name="Separator" 
+                            BorderBrush="Gray"
+                            Grid.Column="0"
+                            Grid.ColumnSpan="5">
                             <DockPanel x:Name="Panel" Background="{Binding Path=(themes:ThemeManager.WorkspaceBackgroundBrush)}">
                                 <Button x:Name="AddButton" DockPanel.Dock="Right" Content="+"
                                         BorderThickness="0" Padding="5,0,5,0" Background="Transparent"
@@ -642,13 +656,48 @@
                                 <TabPanel IsItemsHost="true" Background="Transparent" />
                             </DockPanel>
                         </Border>
+                        
+                        <ContentPresenter 
+                            Grid.Row="1"
+                            Margin="0,2,0,2"
+                            ContentSource="{Binding LeftPanel, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:DynamicTabControl}}" />
+ 
+                        <syncfusion:SfGridSplitter 
+                            Grid.Row="1" 
+                            Grid.Column="1" 
+                            ResizeBehavior="PreviousAndNext" 
+                            Width="2" 
+                            Background="Transparent"
+                            Visibility="{Binding LeftPanel, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:DynamicTabControl}, Converter={StaticResource DynamicTabControlVisibilityConverter}}"
+                            Template="{StaticResource VerticalSplitter}"/>                        
+                        
                         <Border
                             x:Name="Content"
                             Grid.Row="1"
+                            Grid.Column="2"
                             Background="{Binding Path=(themes:ThemeManager.WorkspaceBackgroundBrush)}"
                             BorderThickness="0">
-                            <ContentPresenter ContentSource="SelectedContent" />
+                            <ContentPresenter
+                                x:Name="PART_SelectedContentHost"
+                                ContentSource="SelectedContent" 
+                                />
                         </Border>
+                        
+                        <syncfusion:SfGridSplitter 
+                            Grid.Row="1" 
+                            Grid.Column="3" 
+                            ResizeBehavior="PreviousAndNext" 
+                            Width="4" 
+                            Background="Transparent"
+                            Visibility="{Binding RightPanel, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:DynamicTabControl}, Converter={StaticResource DynamicTabControlVisibilityConverter}}"
+                            Template="{StaticResource VerticalSplitter}"/>                        
+
+                        
+                        <ContentPresenter 
+                            Grid.Row="1"
+                            Grid.Column="4"
+                            Margin="0,2,0,2"
+                            ContentSource="RightPanel" />
                     </Grid>
                     <ControlTemplate.Triggers>