WPF标签页眉控件,其中包含滚动按钮,可移动标签项和每个标签中的关闭按钮

目录

介绍

背景

使用代码

自定义

实现

注释


介绍

对于许多应用程序,希望有一个带有可滚动,重新排列和关闭的选项卡项的选项卡控件。幸运的是,使用标准WPF组件来实现此目标并不难。

本文介绍了一个选项卡页眉控件,其中包含可使用左右箭头按钮滚动并使用简单的拖动操作重新排列的项目。我决定创建一个选项卡页眉控件,而不是一个完整的选项卡控件,以允许更大程度的自定义。将选项卡页眉控件与其他WPF控件组合在一起以创建完整的选项卡控件非常容易。

选项卡页眉控件包括许多依赖项属性,以允许自定义,例如,用于选定和未选定选项卡背景的画笔。

该示例代码包括以下演示应用程序:

顶部选项卡控件包含四个选项卡项。选项卡页眉的每一侧都有左右滚动按钮。默认情况下,滚动按钮绘制为简单的绿色三角形。最右边是显示弹出菜单的按钮,允许用户选择以下选项卡项之一:

中间的标签控件具有标签内容窗格下面的标签,以及滚动按钮的自定义模板。

底部的标签控件具有标签内容窗格上方的标签,以及每个标签项的自定义模板。

主窗口底部的控件允许用户配置字体,标签边框和背景颜色。请注意,该设置不适用于第三个选项卡控件,因为它使用了自定义项目容器样式。

每个选项卡控件的一个关键功能是能够通过将选项卡项拖动到新位置来重新排列它们。

背景

您将需要对C#和Windows开发有充分的了解,并需要WPF的基础知识。

使用代码

XAML中,第一个标签控件由标签页眉控件、按钮和简单标签构成,以显示当前标签项目的内容。选项卡标题控件的定义如下:

<wpfcontrollibrary:TabHeaderControl Grid.Row="1" Grid.Column="0"
x:Name="_tabHeader1" ItemsSource="{Binding ListBoxItems}"
SelectedItem="{Binding SelectedHeader, Mode=TwoWay}">
    <wpfcontrollibrary:TabHeaderControl.DisplayMemberPath>
    HeaderText</wpfcontrollibrary:TabHeaderControl.DisplayMemberPath>
    <wpfcontrollibrary:TabHeaderControl.SelectedTabBackground>
        <Binding Path="SelectedTabBackground" Mode="TwoWay"/>
    </wpfcontrollibrary:TabHeaderControl.SelectedTabBackground>
    <wpfcontrollibrary:TabHeaderControl.UnselectedTabBackground>
        <Binding Path="UnselectedTabBackground" Mode="TwoWay"/>
    </wpfcontrollibrary:TabHeaderControl.UnselectedTabBackground>
    <wpfcontrollibrary:TabHeaderControl.SelectedTabBorderThickness>
        <Binding Path="SelectedTabBorderThickness_Top"/>
    </wpfcontrollibrary:TabHeaderControl.SelectedTabBorderThickness>
    <wpfcontrollibrary:TabHeaderControl.SelectedTabForeground>Black
    </wpfcontrollibrary:TabHeaderControl.SelectedTabForeground>
    <wpfcontrollibrary:TabHeaderControl.UnselectedTabForeground>White
    </wpfcontrollibrary:TabHeaderControl.UnselectedTabForeground>
    <wpfcontrollibrary:TabHeaderControl.FontSize>
        <Binding Path="FontSize"/>
    </wpfcontrollibrary:TabHeaderControl.FontSize>
    <wpfcontrollibrary:TabHeaderControl.FontFamily>
        <Binding Path="FontFamily"/>
    </wpfcontrollibrary:TabHeaderControl.FontFamily>
    <wpfcontrollibrary:TabHeaderControl.DisabledArrowBrush>Transparent
    </wpfcontrollibrary:TabHeaderControl.DisabledArrowBrush>
</wpfcontrollibrary:TabHeaderControl>

以上大部分内容都是自我解释。通过TabHeaderItemItemsSource属性分配实例的可观察集合来填充选项卡列表。所述TabHeaderItem类的定义如下:

class TabHeaderItem
{
    public string Label { get; set; }
    public int ID { get; set; }

    public string HeaderText
    {
        get
        {
            return Label + " : " + ID;
        }
    }
}

DisplayMemberPath属性的行为方式与ListBoxDisplayMemberPath属性完全相同。它设置为HeaderText,因此每个选项卡都显示由关联TabHeaderItem实例的HeaderText属性返回的文本。

有许多属性可控制选项卡项的外观。因此,UnselectedTabBackground属性为未选择的选项卡定义背景画笔。

第二个选项卡控件类似,除了选项卡标题项在选项卡内容下方,并且滚动按钮已重新设置样式。

第三个选项卡控件最有趣,因为它覆盖TabHeaderControlItemContainerStyle属性。这样可以完全自定义标签的外观和功能。在这种情况下,大多数属性如UnselectedTabBackground都不会使用。该示例定义了一个带有文本字符串和关闭按钮的选项卡项,其中关闭功能在后面的代码中实现。ItemContainerStyle属性定义如下:

<wpfcontrollibrary:TabHeaderControl Grid.Row="7" Grid.Column="0" 

 x:Name="_tabHeader3" ItemsSource="{Binding ListBoxItems}" 

 SelectedItem="{Binding SelectedHeader, Mode=TwoWay}">
    <wpfcontrollibrary:TabHeaderControl.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="FrameworkElement.Margin" Value="0"/>
            <Setter Property="FocusVisualStyle" Value="{x:Null}" />
            <Setter Property="Padding" Value="0" />
            <Setter Property="Margin" Value="0" />
            <EventSetter Event="PreviewMouseLeftButtonDown" 

             Handler="ListBoxItem_PreviewMouseLeftButtonDown" />

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <Border Background="{TemplateBinding Background}" 

                         Padding="4" 

                         SnapsToDevicePixels="true" BorderThickness="0" 

                         CornerRadius="20,10,0,0">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="4"/>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="2"/>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="2"/>
                                </Grid.ColumnDefinitions>
                                <Label Grid.Column="1" FontSize="14" 

                                 Foreground="{TemplateBinding Foreground}" 

                                 Background="{TemplateBinding Background}" 

                                 Width="Auto" Padding="2,0,2,0" Margin="0" 

                                 VerticalAlignment="Center">
                                    <TextBlock>
                                        <Run Text="{Binding Label}"/><Run Text=" ("/>
                                        <Run Text="{Binding ID}"/><Run Text=")"/>
                                    </TextBlock>
                                </Label>
                                <Button Grid.Column="3" Width="20" Height="20" 

                                 Content="X" FontSize="12" 

                                 Background="{TemplateBinding Background}" 

                                 Foreground="{TemplateBinding Foreground}" 

                                 BorderThickness="0" Click="Button_Click"/>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="Orange"/>
                    <Setter Property="Foreground" Value="Black"/>
                </Trigger>
                <Trigger Property="IsSelected" Value="False">
                    <Setter Property="Background" Value="DarkSlateBlue"/>
                    <Setter Property="Foreground" Value="White"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </wpfcontrollibrary:TabHeaderControl.ItemContainerStyle>
    <wpfcontrollibrary:TabHeaderControl.FontFamily>
        <Binding Path="FontFamily"/>
    </wpfcontrollibrary:TabHeaderControl.FontFamily>
</wpfcontrollibrary:TabHeaderControl>

触发器用于选择和未选择时设置选项卡的样式。

需要注意的有趣一点是数据模板的以下摘录:

<EventSetter Event="PreviewMouseLeftButtonDown" 

 Handler="ListBoxItem_PreviewMouseLeftButtonDown" />

ListBoxItem_PreviewMouseLeftButtonDown处理程序的按钮单击事件之前调用。sender参数是ListBoxItem允许后面的代码确定与后续按钮按下关联的选项卡项目的索引。处理程序代码如下:

private void ListBoxItem_PreviewMouseLeftButtonDown
(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    System.Windows.Controls.ListBoxItem listBoxItem = 
                   sender as System.Windows.Controls.ListBoxItem;
    if (listBoxItem == null)
    {
        return;
    }

    TabHeaderItem tabHeaderItem = listBoxItem.DataContext as TabHeaderItem;
    if (tabHeaderItem == null)
    {
        return;
    }

    _listBoxItemIndex = (DataContext as MainWindowModel).ListBoxItems.IndexOf(tabHeaderItem);
}

因此,_listBoxItemIndex值定义了与随后的关闭按钮单击事件关联的列表框项目的索引。

自定义

可以使用以下依赖项属性来修改控件的外观和行为:

ItemsSource

获取或设置用于生成选项卡内容的集合

SelectedItem

获取或设置当前选定的项目

SelectedIndex

获取或设置当前选定标签的索引,如果没有选定标签,则返回-1

SelectedValue

获取或设置当前选择的值

SelectedValuePath

获取或设置用于从SelectedItem获取SelectedValue的路径

ArrowTemplate

获取或设置箭头按钮的控制模板。右手按钮与左手按钮相同,只是旋转了180度。

DisplayMemberPath

获取或设置源对象上的值的路径,以用作对象的视觉表示

SelectedTabBackground

获取或设置用于所选选项卡背景的画笔

UnselectedTabBackground

获取或设置用于未选中选项卡的背景的画笔

SelectedTabBorderThickness

获取或设置所选标签的边框粗细

SelectedTabForeground

获取或设置用于选定选项卡的前景的画笔

UnselectedTabForeground

获取或设置用于未选中选项卡的前景的画笔

ItemContainerStyle

获取或设置应用于为每个项目生成的容器元素的Style

 

 

ItemContainerStyle是最强大的依赖属性,因为它允许每个标签项目的完全定制。该演示应用程序包括带有自定义ItemContainerStyle标签的页眉控件。

另外,控件中显示的文本遵循用户控件的标准FontSizeFontFamilyFontStyle的依赖特性。

实现

选项卡页眉控件使用两个按钮控件和一个水平列表的修改列表框实现。列表框由TabHeader类实现,该类派生自标准ListBox类,并增加了重新排列项目的功能。尽管确定如何实现所需的功能并非易事,但是代码很容易理解。

注释

选项卡页眉控件不支持垂直选项卡。通过修改基础TabHeader类来添加它并不难。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值