我一直在为 WPF 开发一个 SplitButton 控件,它基本上已经完成了,但我正在尝试检查所有可以在其上设置的可能属性,并确保它们得到实际实现。我主要只剩下两个属性要实现,即 ItemTemplate
和 ItemTemplateSelector
(和 AlternationCount
,好的,所以 3 个属性)。
通过将 ContentTemplate
和 ContentTemplateSelector
绑定(bind)到 HeaderTemplate
和 HeaderTemplateSelector
一个 ContentPresenter
。不过,这是针对控件的按钮部分。对于控件的拖放部分,我使用了 Popup、Border 和 ItemsPresenter
。问题是我不知道如何为 ItemsPresenter
设置 ItemTemplate
和 ItemTemplateSelector
属性。
有什么想法吗?
更新: SplitButton 的完整源代码现在可在以下位置获得: http://anothersplitbutton.codeplex.com/
这是 Luna.NormalColor.xaml 文件:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:WpfSplitButton="clr-namespace:WpfSplitButton"
xmlns:mwt="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Luna"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- SplitButtonHeader Style -->
<Style x:Key="{x:Type WpfSplitButton:SplitButtonHeader}"
TargetType="{x:Type WpfSplitButton:SplitButtonHeader}">
<Style.Resources>
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2"
StrokeThickness="1"
Stroke="Black"
StrokeDashArray="1 2"
SnapsToDevicePixels="True" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Style.Setters>
<Setter Property="FocusVisualStyle"
Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="PastLeftDetection"
Value="True" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<mwt:ButtonChrome x:Name="Chrome"
BorderBrush="{TemplateBinding Border.BorderBrush}"
RenderDefaulted="{TemplateBinding Button.IsDefaulted}"
RenderMouseOver="{TemplateBinding UIElement.IsMouseOver}"
RenderPressed="{TemplateBinding ButtonBase.IsPressed}"
SnapsToDevicePixels="True">
<Grid Background="{TemplateBinding ButtonBase.Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ButtonBase.ContentTemplate}"
ContentTemplateSelector="{TemplateBinding ButtonBase.ContentTemplateSelector}"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
Margin="{TemplateBinding Control.Padding}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" />
<Border x:Name="PART_DropDownInitiator"
Background="Transparent"
BorderBrush="{Binding Path=BorderBrush, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WpfSplitButton:SplitButtonHeader}}}"
BorderThickness="1,0,0,0"
Grid.Column="1"
HorizontalAlignment="Stretch"
Margin="0,0,0,0"
Padding="4,0,4,0"
VerticalAlignment="Stretch">
<Path Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WpfSplitButton:SplitButtonHeader}}}"
VerticalAlignment="Center">
<Path.Style>
<Style>
<Setter Property="Path.Fill"
Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Style.Triggers>
<Trigger Property="WpfSplitButton:SplitButton.IsMouseOver"
Value="True">
<Setter Property="Path.Fill"
Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
</Trigger>
</Style.Triggers>
</Style>
</Path.Style>
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure IsClosed="True"
StartPoint="0,0">
<PathFigure.Segments>
<PathSegmentCollection>
<LineSegment Point="8,0" />
<LineSegment Point="4,5" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</Border>
</Grid>
</mwt:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsKeyboardFocused"
Value="True">
<Setter TargetName="Chrome"
Property="mwt:ButtonChrome.RenderDefaulted"
Value="True" />
</Trigger>
<Trigger Property="ToggleButton.IsChecked"
Value="True">
<Setter TargetName="Chrome"
Property="mwt:ButtonChrome.RenderPressed"
Value="True" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
<!-- SplitButton -->
<Style x:Key="{x:Type WpfSplitButton:SplitButton}"
TargetType="{x:Type WpfSplitButton:SplitButton}">
<Style.Resources>
<LinearGradientBrush x:Key="ButtonNormalBackgroundFill"
EndPoint="0.5,1"
StartPoint="0.5,0">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FFFFFFFF"
Offset="0" />
<GradientStop Color="#FFF0F0EA"
Offset="0.9" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<SolidColorBrush x:Key="ButtonBorder"
Color="#FF003C74" />
</Style.Resources>
<Setter Property="AutoUpdateHeader"
Value="True" />
<Setter Property="Background"
Value="{StaticResource ButtonNormalBackgroundFill}" />
<Setter Property="BorderBrush"
Value="{StaticResource ButtonBorder}" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="Padding"
Value="4,4,4,4" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type WpfSplitButton:SplitButton}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<WpfSplitButton:SplitButtonHeader x:Name="PART_Header"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"
Cursor="{TemplateBinding Cursor}"
Foreground="{TemplateBinding Foreground}"
Grid.Row="0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Stretch"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
<Popup x:Name="PART_Popup"
AllowsTransparency="True"
Grid.Row="1"
IsOpen="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
MinWidth="{Binding Path=ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WpfSplitButton:SplitButton}}}"
Placement="Bottom"
PlacementTarget="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WpfSplitButton:SplitButton}}}"
PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}"
StaysOpen="False">
<mwt:SystemDropShadowChrome Color="Transparent">
<Border x:Name="DropDownBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</mwt:SystemDropShadowChrome>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
更新 2 我尝试用 ItemsControl 关闭 ItemsPresenter,但我似乎无法让 ItemTemplate 属性执行任何操作。这是代码的更改部分:
<ItemsControl DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WpfSplitButton:SplitButton}}}"
AlternationCount="{TemplateBinding AlternationCount}"
IsTabStop="{TemplateBinding IsTabStop}"
IsTextSearchEnabled="{TemplateBinding IsTextSearchEnabled}"
ItemContainerStyle="{TemplateBinding ItemContainerStyle}"
ItemContainerStyleSelector="{TemplateBinding ItemContainerStyleSelector}"
ItemBindingGroup="{TemplateBinding ItemBindingGroup}"
ItemsPanel="{TemplateBinding ItemsPanel}"
ItemsSource="{Binding Path=Items}"
ItemStringFormat="{TemplateBinding ItemStringFormat}"
ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="HELLO" />
</DataTemplate>
</ItemsControl.ItemTemplate>
最佳答案
您是否考虑过使用 ItemsControl
而不是 ItemsPresenter
?这将为您提供 ItemTemplate
和 ItemTemplateSelector
属性以及 AlternationCount
属性。
更新: 我使用上面发布的 ItemsControl 使它工作得很好,使用以下行绑定(bind)到 Classic.xaml 文件中的 ItemsTemplate 属性:
ItemTemplate="{TemplateBinding ItemsTemplate, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WpfSplitButton:SplitButton}}}"
然后在您的主窗口的资源中,我刚刚添加了以下模板:
<DataTemplate x:Key="Test">
<MenuItem Header="{Binding}" />
</DataTemplate>
然后我在 SplitButton 上设置 ItemTemplate 属性:
ItemTemplate="{StaticResource Test}"
所以只需连接您的 ItemSource 就可以开始了...我只是在后面的代码中使用了一个简单的字符串 []... 希望这对您有所帮助!
关于c# - WPF - 为 ItemsPresenter 实现 ItemTemplate?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1014881/