#c# #wpf #user-controls
#c# #wpf #пользовательские элементы управления
Вопрос:
Я пытаюсь создать tabcontrol, где tabitems имеют изображение, текст и кнопку закрытия и сохраняют его как usercontrol. То, что у меня сейчас есть, — это этот образ. Код XAML для этого приведен ниже
Главное окно
<Window x:Class="TabControlExperiments.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TabControlExperiments"
mc:Ignorable="d"
xmlns:uc ="clr-namespace:TabControlExperiments.UserControls"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TabControl>
<TabItem>
<TabItem.Header>
<uc:TabHeader Text="This is a new Tab" Image="../Images/ThreeCircles.png"/>
</TabItem.Header>
</TabItem>
</TabControl>
</Grid>
</Window>
И пользовательский контроль в заголовке табуляции:
<UserControl x:Class="TabControlExperiments.UserControls.TabHeader"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TabControlExperiments.UserControls"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0"
Height="20"
Source="{Binding Image, RelativeSource={RelativeSource AncestorType={x:Type local:TabHeader}}}" />
<Label Grid.Column="1"
Content="{Binding Text, RelativeSource={RelativeSource AncestorType={x:Type local:TabHeader}}}" />
<Canvas Grid.Column="2"
Width="12"
Height="12"
Background="Transparent"
MouseDown="Canvas_MouseDown">
<Path Canvas.Left="2"
Canvas.Top="1"
Data="M0,0 L10,10 M10,0 L0,10"
Stroke="Black"
StrokeThickness="2"
StrokeEndLineCap="Round" />
</Canvas>
</Grid>
</UserControl>
Обработчик события Canvas_MouseDown удаляет tabitem (где находится usercontrol) из его родительского элемента.
Как вы можете видеть, в этом проекте я должен явно определять заголовок для элемента tabitem каждый раз, когда я создаю вкладку либо в XAML, либо в коде. Есть ли какой-нибудь способ создать пользовательский элемент управления для элемента управления tab или элемента tab, чтобы при его добавлении я мог напрямую указывать текст и изображение? Что-то вроде этого.
<TabControl>
<uc:TabItem Text="This is a new Tab"
Image="../Images/ThreeCircles.png">
<TextBlock />
</uc:TabItem>
</TabControl>
Я попытался создать пользовательские стили для элемента вкладки, но это не помогло, так как я не был уверен, как создать обработчик событий для закрытия вкладки.
Ответ №1:
- Если вы хотите использовать стиль TabItem по умолчанию, вы можете задать как текст, так и изображение для TabItem.
- Если вы находитесь в этой ситуации.Вам нужно определить свой собственный шаблон TabItem и добавить к нему дополнительные атрибуты.
attactedProperty
/// <summary>
/// 附加属性:图标
/// </summary>
public static class AttachedIcon
{
static readonly Type OwnerType = typeof(AttachedIcon);
#region Value
/// <summary>
/// 获取或设置 <see cref="DependencyObject"/> 的附加图标
/// </summary>
public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached("Value", typeof(object), OwnerType, new PropertyMetadata(default(object)));
/// <summary>
/// 设置 <see cref="DependencyObject"/> 的 <see cref="ValueProperty"/> 属性值
/// </summary>
/// <param name="element"></param>
/// <param name="value"></param>
public static void SetValue(DependencyObject element, object value)
{
element.SetValue(ValueProperty, value);
}
/// <summary>
/// 获取 <see cref="DependencyObject"/> 的 <see cref="ValueProperty"/> 属性值
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
public static object GetValue(DependencyObject element)
{
return (object) element.GetValue(ValueProperty);
}
#endregion
}
xaml.cs
<ControlTemplate TargetType="{x:Type TabItem}">
<Border x:Name="Border" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<StackPanel
Orientation="Horizontal" Focusable="False"
HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
Margin="{TemplateBinding Padding}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}">
<Image x:Name="IconPresenter" Source="{TemplateBinding i:AttachedIcon.Value}"></Image>
<ContentPresenter x:Name="ContentPresenter" ContentSource="Header" RecognizesAccessKey="True" />
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource PrimaryBrush}"/>
<Setter TargetName="ContentPresenter" Property="TextElement.Foreground" Value="{StaticResource PrimaryBrush}"/>
</Trigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabControl}},Path=TabStripPlacement}" Value="{x:Static Dock.Top}">
<Setter TargetName="Border" Property="BorderThickness" Value="0,0,0,3"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabControl}},Path=TabStripPlacement}" Value="{x:Static Dock.Left}">
<Setter TargetName="Border" Property="BorderThickness" Value="0,0,3,0"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabControl}},Path=TabStripPlacement}" Value="{x:Static Dock.Right}">
<Setter TargetName="Border" Property="BorderThickness" Value="3,0,0,0"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabControl}},Path=TabStripPlacement}" Value="{x:Static Dock.Bottom}">
<Setter TargetName="Border" Property="BorderThickness" Value="0,3,0,0"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>