views:

531

answers:

1

I've got a UI with a fairly standard look and feel. It has a column of icons on the left side which when clicked open a different user control on the right side. Currently I'm using separate controls for the selection icons and the usercontrol containment. I'm having strange focus issues that I am tired of trying to mitigate and am wondering if I could style a tabcontrol to look like my UI (under the assumption a tabcontrol would not have focus issues when navigating tabs).

Here is a screenshot of the basic UI. The styling is mostly about how to get the tabcontrols page selection to look like my column of icons. Anyone want to throw their hat in the ring as to how I might accomplish this with a tabcontrol? My xaml is pretty weak at this point.

alt text

+3  A: 
<TabControl TabStripPlacement="Left">
    ...
</TabControl>

Then you put the icons in the Header property of the TabItems and the UserControls in the Content property. That will get you about halfway there. If you want the exact same look you'll need to retemplate the TabControl and TabItem by copying the current template (use Blend or ShowMeTheTemplate to copy the current template) and modifying it as needed. But just changing those properties will let you test whether a TabControl gets rid of your focus issues.

Edit: Here's an example template that should be pretty close to your screenshot

<Style TargetType="{x:Type TabItem}">
    <Setter Property="Background" Value="Transparent" />

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabItem}">

                <Border x:Name="PART_Border" Background="{TemplateBinding Background}" BorderThickness="1" BorderBrush="LightGray" Margin="2">
                    <ContentPresenter ContentSource="Header" Margin="2" />
                </Border>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter TargetName="PART_Border" Property="BorderBrush" Value="Black" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="{x:Type TabControl}">
    <Setter Property="TabStripPlacement" Value="Left" />
    <Setter Property="Margin" Value="2" />
    <Setter Property="Padding" Value="2"    />
    <Setter Property="Background" Value="White" />


    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabControl}">
                <Grid ClipToBounds="True" SnapsToDevicePixels="True" KeyboardNavigation.TabNavigation="Local">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Name="ColumnDefinition0" />
                        <ColumnDefinition Width="0" Name="ColumnDefinition1" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" Name="RowDefinition0" />
                        <RowDefinition Height="*" Name="RowDefinition1" />
                    </Grid.RowDefinitions>

                    <Border x:Name="HeaderBorder" 
                            BorderBrush="Black" 
                            BorderThickness="1" 
                            CornerRadius="5" 
                            Background="#FAFAFA"
                            Margin="0,0,0,5">
                        <TabPanel IsItemsHost="True"
                                  Name="HeaderPanel" 
                                  Panel.ZIndex="1" 
                                  KeyboardNavigation.TabIndex="1"
                                  Grid.Column="0" 
                                  Grid.Row="0" 
                         />
                    </Border>

                    <Grid Name="ContentPanel" 
                          KeyboardNavigation.TabIndex="2" 
                          KeyboardNavigation.TabNavigation="Local" 
                          KeyboardNavigation.DirectionalNavigation="Contained" 
                          Grid.Column="0" 
                          Grid.Row="1">
                        <Border Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}" 
                                BorderThickness="{TemplateBinding BorderThickness}"
                                CornerRadius="5">
                            <ContentPresenter Content="{TemplateBinding SelectedContent}" 
                                              ContentTemplate="{TemplateBinding SelectedContentTemplate}" 
                                              ContentStringFormat="{TemplateBinding SelectedContentStringFormat}" 
                                              ContentSource="SelectedContent" 
                                              Name="PART_SelectedContentHost" 
                                              Margin="2" 
                                              SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" 
                            />
                        </Border>
                    </Grid>
                </Grid>

                <ControlTemplate.Triggers>
                    <Trigger Property="TabControl.TabStripPlacement" Value="Bottom">
                        <Setter TargetName="HeaderPanel" Property="Grid.Row" Value="1" />
                        <Setter TargetName="ContentPanel" Property="Grid.Row" Value="0" />
                        <Setter TargetName="RowDefinition0" Property="RowDefinition.Height" Value="*" />
                        <Setter TargetName="RowDefinition1" Property="RowDefinition.Height" Value="Auto" />
                        <Setter TargetName="HeaderBorder" Property="FrameworkElement.Margin" Value="0,5,0,0" />
                    </Trigger>
                    <Trigger Property="TabControl.TabStripPlacement" Value="Left">
                        <Setter TargetName="HeaderPanel" Property="Grid.Row" Value="0" />
                        <Setter TargetName="ContentPanel" Property="Grid.Row" Value="0" />
                        <Setter TargetName="HeaderPanel" Property="Grid.Column" Value="0" />
                        <Setter TargetName="ContentPanel" Property="Grid.Column" Value="1" />
                        <Setter TargetName="ColumnDefinition0" Property="ColumnDefinition.Width" Value="Auto" />
                        <Setter TargetName="ColumnDefinition1" Property="ColumnDefinition.Width" Value="*" />
                        <Setter TargetName="RowDefinition0" Property="RowDefinition.Height" Value="*" />
                        <Setter TargetName="RowDefinition1" Property="RowDefinition.Height" Value="0" />
                        <Setter TargetName="HeaderBorder" Property="FrameworkElement.Margin" Value="0,0,5,0" />
                    </Trigger>
                    <Trigger Property="TabControl.TabStripPlacement" Value="Right">
                        <Setter TargetName="HeaderPanel" Property="Grid.Row" Value="0" />
                        <Setter TargetName="ContentPanel" Property="Grid.Row" Value="0" />
                        <Setter TargetName="HeaderPanel" Property="Grid.Column" Value="1" />
                        <Setter TargetName="ContentPanel" Property="Grid.Column" Value="0" />
                        <Setter TargetName="ColumnDefinition0" Property="ColumnDefinition.Width" Value="*" />
                        <Setter TargetName="ColumnDefinition1" Property="ColumnDefinition.Width" Value="Auto" />
                        <Setter TargetName="RowDefinition0" Property="RowDefinition.Height" Value="*" />
                        <Setter TargetName="RowDefinition1" Property="RowDefinition.Height" Value="0" />
                        <Setter TargetName="HeaderBorder" Property="FrameworkElement.Margin" Value="5,0,0,0" />
                    </Trigger>
                    <Trigger Property="UIElement.IsEnabled" Value="False">
                        <Setter Property="TextElement.Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

It's basically a copy of the normal TabControl with some Borders added and removed. Hope that helps.

Bryan Anderson
Thanks for the response. It really is the retemplating that I'm looking for advice on. It's the part I really think could block this from being a viable solution.
BrettRobi
I can post an example when I get home in a few hours.
Bryan Anderson
Brett, I expect you'll find that retemplating won't be that bad. It sounds scary, but once you get into it is kinda fun. Plus, having the old template to revert to means you can always start over if worst comes to worst.
Ed Gonzalez
Thanks for the example Bryan. I'll take a closer look at it in the next few days.
BrettRobi
Thanks again Bryan. I think I can make this work!
BrettRobi