c# – WPF – 为ItemsPresenter实现ItemTemplate?

我一直在为
WPF开发一个SplitButton控件,它已基本完成,但我正在尝试查看可以在其上设置的所有可能的属性,并确保它们实际上已实现.我大多只剩下两个属性来实现,即ItemTemplate和ItemTemplateSelector(以及AlternationCount,好的3个属性).

我能够通过在ContentPresenter上将ContentTemplate和ContentTemplateSelector绑定到它们来使HeaderTemplate和HeaderTemplateSelector工作.这是控件的按钮部分.对于控件的drop-drop部分,我使用的是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使用以下行绑定到Classic.xaml文件中的ItemsTemplate属性,使其工作得很好:

 ItemTemplate="{TemplateBinding ItemsTemplate, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WpfSplitButton:SplitButton}}}"

然后在您的MainWindow的资源中,我刚刚添加了以下模板:

<DataTemplate x:Key="Test">
    <MenuItem Header="{Binding}" />
</DataTemplate>

然后我在SplitButton上设置ItemTemplate属性:

ItemTemplate="{StaticResource Test}"

所以只需连接你的ItemSource就可以了…我只是在后面的代码中使用了一个简单的字符串[] …
希望这可以帮助!

点赞