WPF - реализовать ItemTemplate для ItemsPresenter? - PullRequest
4 голосов
/ 19 июня 2009

Я работал над элементом управления SplitButton для WPF, и он в основном завершен, но я пытаюсь просмотреть все возможные свойства, которые можно установить для него, и убедиться, что они действительно реализованы. В основном у меня осталось только два свойства для реализации: ItemTemplate и ItemTemplateSelectorAlternationCount, ладно, так 3 свойства).

Я смог заставить работать HeaderTemplate и HeaderTemplateSelector, привязав ContentTemplate и ContentTemplateSelector к ним на ContentPresenter. Это для кнопочной части элемента управления. Для выпадающего элемента управления я использую Popup, Border и ItemsPresenter. Проблема в том, что я не могу понять, как установить свойства ItemTemplate и ItemTemplateSelector для ItemsPresenter.

Есть идеи?


Обновление : Полный исходный код для 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 Я попытался отключить ItemsPresenter с помощью ItemsControl, но я не могу заставить свойство 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>

1 Ответ

2 голосов
/ 24 июня 2009

Рассматривали ли вы использовать ItemsControl вместо ItemsPresenter? Это даст вам свойство ItemTemplate и ItemTemplateSelector, а также свойство AlternationCount.

Обновление: Я сделал так, чтобы он работал нормально, используя ItemsControl, как вы опубликовали выше, используя следующую строку для привязки к свойству ItemsTemplate в вашем файле Classic.xaml:

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

Затем в ресурсах вашего MainWindow я просто добавил следующий шаблон:

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

Затем я устанавливаю свойство ItemTemplate на кнопку SplitButton:

ItemTemplate="{StaticResource Test}"

Так что просто подключите ваш ItemSource, и все готово ... Я просто использовал простую строку [] в коде позади ... Надеюсь, это поможет!

...