简体   繁体   English

具有多个按钮的WPF扩展器

[英]WPF Expander with Multiple Buttons

I have a requirement to include buttons that will trigger logic on an Expander in WPF. 我需要包含将在WPF中的Expander上触发逻辑的按钮。 I have included an image below. 我在下面列出了一张图片。

在此输入图像描述

I'm unsure how to accomplish this in WPF, or if its possible. 我不确定如何在WPF中完成此任务,或者如果可能的话。 The buttons needs to wire to backend fucntionality to create objects. 按钮需要连接到后端功能以创建对象。 Each is an expander and should have those buttons on the right of the expander header regardless if they are expanded or not. 每个都是一个扩展器,并且应该在扩展器头的右侧有这些按钮,无论它们是否被扩展。 The button should call _Click method on the code behind when clicked. 单击时,该按钮应在后面的代码上调用_Click方法。

Can this be done with an expander and how can I accomplish this? 这可以用扩展器来完成,我该如何实现?

To make your Button s appear at the extreme right, you have to use a DockPanel as your Expander.HeaderTemplate . 要使Button显示在最右侧,您必须使用DockPanel作为Expander.HeaderTemplate But Expander uses ToggleButton in its top part where expanding circle is shown. Expander在其顶部使用ToggleButton ,其中显示了扩展圆圈。 This ToggleButton is having its HorizontalAlignment set as Left. ToggleButton将其HorizontalAlignment设置为Left。 So, we need to change this setting in the Style with ExpanderDownHeaderStyle Key as 因此,我们需要在Style使用ExpanderDownHeaderStyle Key更改此设置

<ContentPresenter Grid.Column="1" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" ... />

Copy paste the below piece of XAML as it is. 复制粘贴下面的XAML原样。

<Window.Resources>
        <SolidColorBrush x:Key="Expander.MouseOver.Circle.Stroke" Color="#FF3C7FB1"/>
        <SolidColorBrush x:Key="Expander.MouseOver.Circle.Fill" Color="Transparent"/>
        <SolidColorBrush x:Key="Expander.MouseOver.Arrow.Stroke" Color="#222"/>
        <SolidColorBrush x:Key="Expander.Pressed.Circle.Stroke" Color="#FF526C7B"/>
        <SolidColorBrush x:Key="Expander.Pressed.Circle.Fill" Color="Transparent"/>
        <SolidColorBrush x:Key="Expander.Pressed.Arrow.Stroke" Color="#FF003366"/>
        <SolidColorBrush x:Key="Expander.Disabled.Circle.Stroke" Color="DarkGray"/>
        <SolidColorBrush x:Key="Expander.Disabled.Circle.Fill" Color="Transparent"/>
        <SolidColorBrush x:Key="Expander.Disabled.Arrow.Stroke" Color="#666"/>
        <SolidColorBrush x:Key="Expander.Static.Circle.Fill" Color="Transparent"/>
        <SolidColorBrush x:Key="Expander.Static.Circle.Stroke" Color="DarkGray"/>
        <SolidColorBrush x:Key="Expander.Static.Arrow.Stroke" Color="#666"/>
        <Style x:Key="ExpanderRightHeaderStyle" TargetType="{x:Type ToggleButton}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Border Padding="{TemplateBinding Padding}">
                            <Grid Background="Transparent" SnapsToDevicePixels="False">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="19"/>
                                    <RowDefinition Height="*"/>
                                </Grid.RowDefinitions>
                                <Grid>
                                    <Grid.LayoutTransform>
                                        <TransformGroup>
                                            <TransformGroup.Children>
                                                <TransformCollection>
                                                    <RotateTransform Angle="-90"/>
                                                </TransformCollection>
                                            </TransformGroup.Children>
                                        </TransformGroup>
                                    </Grid.LayoutTransform>
                                    <Ellipse x:Name="circle" Fill="{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center" Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}" VerticalAlignment="Center" Width="19"/>
                                    <Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="{StaticResource Expander.Static.Arrow.Stroke}" StrokeThickness="2" VerticalAlignment="Center"/>
                                </Grid>
                                <ContentPresenter HorizontalAlignment="Center" Margin="0,4,0,0" Grid.Row="1" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Top"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsChecked" Value="true">
                                <Setter Property="Data" TargetName="arrow" Value="M 1,4.5  L 4.5,1  L 8,4.5"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
                                <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
                                <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
                                <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
                                <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
                                <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
                                <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="ExpanderUpHeaderStyle" TargetType="{x:Type ToggleButton}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Border Padding="{TemplateBinding Padding}">
                            <Grid Background="Transparent" SnapsToDevicePixels="False">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="19"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <Grid>
                                    <Grid.LayoutTransform>
                                        <TransformGroup>
                                            <TransformGroup.Children>
                                                <TransformCollection>
                                                    <RotateTransform Angle="180"/>
                                                </TransformCollection>
                                            </TransformGroup.Children>
                                        </TransformGroup>
                                    </Grid.LayoutTransform>
                                    <Ellipse x:Name="circle" Fill="{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center" Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}" VerticalAlignment="Center" Width="19"/>
                                    <Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="{StaticResource Expander.Static.Arrow.Stroke}" StrokeThickness="2" VerticalAlignment="Center"/>
                                </Grid>
                                <ContentPresenter Grid.Column="1" HorizontalAlignment="Left" Margin="4,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsChecked" Value="true">
                                <Setter Property="Data" TargetName="arrow" Value="M 1,4.5  L 4.5,1  L 8,4.5"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
                                <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
                                <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
                                <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
                                <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
                                <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
                                <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="ExpanderLeftHeaderStyle" TargetType="{x:Type ToggleButton}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Border Padding="{TemplateBinding Padding}">
                            <Grid Background="Transparent" SnapsToDevicePixels="False">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="19"/>
                                    <RowDefinition Height="*"/>
                                </Grid.RowDefinitions>
                                <Grid>
                                    <Grid.LayoutTransform>
                                        <TransformGroup>
                                            <TransformGroup.Children>
                                                <TransformCollection>
                                                    <RotateTransform Angle="90"/>
                                                </TransformCollection>
                                            </TransformGroup.Children>
                                        </TransformGroup>
                                    </Grid.LayoutTransform>
                                    <Ellipse x:Name="circle" Fill="{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center" Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}" VerticalAlignment="Center" Width="19"/>
                                    <Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="{StaticResource Expander.Static.Arrow.Stroke}" StrokeThickness="2" VerticalAlignment="Center"/>
                                </Grid>
                                <ContentPresenter HorizontalAlignment="Center" Margin="0,4,0,0" Grid.Row="1" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Top"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsChecked" Value="true">
                                <Setter Property="Data" TargetName="arrow" Value="M 1,4.5  L 4.5,1  L 8,4.5"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
                                <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
                                <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
                                <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
                                <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
                                <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
                                <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="ExpanderHeaderFocusVisual">
            <Setter Property="Control.Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Border>
                            <Rectangle Margin="0" SnapsToDevicePixels="true" Stroke="Black" StrokeThickness="1" StrokeDashArray="1 2"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="ExpanderDownHeaderStyle" TargetType="{x:Type ToggleButton}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Border Padding="{TemplateBinding Padding}">
                            <Grid Background="Transparent" SnapsToDevicePixels="False">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="19"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <Ellipse x:Name="circle" Fill="{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center" Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}" VerticalAlignment="Center" Width="19"/>
                                <Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="{StaticResource Expander.Static.Arrow.Stroke}" StrokeThickness="2" VerticalAlignment="Center"/>
                                <ContentPresenter Grid.Column="1" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Margin="4,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsChecked" Value="true">
                                <Setter Property="Data" TargetName="arrow" Value="M 1,4.5  L 4.5,1  L 8,4.5"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
                                <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
                                <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
                                <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
                                <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
                                <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
                                <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="ExpanderStyle1" TargetType="{x:Type Expander}">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="VerticalContentAlignment" Value="Stretch"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Expander}">
                        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3" SnapsToDevicePixels="true">
                            <DockPanel>
                                <ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}" Content="{TemplateBinding Header}" DockPanel.Dock="Top" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FocusVisualStyle="{StaticResource ExpanderHeaderFocusVisual}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" MinWidth="0" MinHeight="0" Padding="{TemplateBinding Padding}" Style="{StaticResource ExpanderDownHeaderStyle}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                <ContentPresenter x:Name="ExpandSite" DockPanel.Dock="Bottom" Focusable="false" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                            </DockPanel>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsExpanded" Value="true">
                                <Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
                            </Trigger>
                            <Trigger Property="ExpandDirection" Value="Right">
                                <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Right"/>
                                <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Left"/>
                                <Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderRightHeaderStyle}"/>
                            </Trigger>
                            <Trigger Property="ExpandDirection" Value="Up">
                                <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Top"/>
                                <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Bottom"/>
                                <Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderUpHeaderStyle}"/>
                            </Trigger>
                            <Trigger Property="ExpandDirection" Value="Left">
                                <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Left"/>
                                <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Right"/>
                                <Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderLeftHeaderStyle}"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>    

Expander usage 扩展器使用

<Expander Grid.Row="1" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" Style="{DynamicResource ExpanderStyle1}">            
    <Expander.HeaderTemplate>
        <DataTemplate>
            <DockPanel LastChildFill="False" Background="LimeGreen">
                <TextBlock Text="Expander1"/>
                <Button Content="Press" DockPanel.Dock="Right"/>
                <Button Content="Press" DockPanel.Dock="Right"/>
            </DockPanel>
        </DataTemplate>
    </Expander.HeaderTemplate>
    <StackPanel Background="LightSteelBlue"></StackPanel>
</Expander>

Output : 输出:

扩展器右侧的按钮

I'd suggest that you craft a specific class that does the job for you, here is a primitive skeleton along explanations. 我建议你制作一个特定的课程,为你完成这项工作,这里是解释的原始骨架。

On the top there's a sort of bread-crumb bar , which are the actual buttons that when pressed will expand the targeted section. 在顶部有一种面包屑条 ,它是实际的按钮,按下时会扩展目标部分。

在此输入图像描述

ExpanderGroup class, responsible of rendering and some UI logic ExpanderGroup类,负责渲染和一些UI逻辑

There are 2 collections, one for the headers of the bread-crumb bar, the other are for the Expander s themselves. 有两个系列,一个用于面包屑条的标题,另一个用于Expander s本身。

public partial class ExpanderGroup : UserControl
{
    public static readonly DependencyProperty ChildrenProperty = DependencyProperty.Register(
        "Children", typeof (ObservableCollection<Expander>), typeof (ExpanderGroup),
        new PropertyMetadata(default(ObservableCollection<Expander>)));

    public static readonly DependencyProperty ChildrenHeadersProperty = DependencyProperty.Register(
        "ChildrenHeaders", typeof (ObservableCollection<string>), typeof (ExpanderGroup),
        new PropertyMetadata(default(ObservableCollection<string>)));

    public ExpanderGroup()
    {
        InitializeComponent();
        Children = new ObservableCollection<Expander>();
        ChildrenHeaders = new ObservableCollection<string>();
    }

    public ObservableCollection<Expander> Children
    {
        get { return (ObservableCollection<Expander>) GetValue(ChildrenProperty); }
        set { SetValue(ChildrenProperty, value); }
    }

    public ObservableCollection<string> ChildrenHeaders
    {
        get { return (ObservableCollection<string>) GetValue(ChildrenHeadersProperty); }
        set { SetValue(ChildrenHeadersProperty, value); }
    }

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        // find the corresponding expander to toggle button clicked
        // it is very primitive as it expects an exact mapping by name
        var button = (ToggleButton) sender;
        var text = (string) button.Content;
        var expander = Children.Single(s => (string) s.Header == text);

        // toggle expansion status
        expander.IsExpanded = button.IsChecked != null && (bool) button.IsChecked;

        // little helper that expands the root expander
        // (though its template should be changed for better UX)
        RootExpander.IsExpanded = Children.Any(s => s.IsExpanded);
    }
}

Notes: 笔记:

  • I used a really simple logic, ie I retrieve the corresponding Expander according its header, you could enhance that further, either by referring to its index or any other means. 我使用了一个非常简单的逻辑,即我根据其标题检索相应的Expander ,您可以通过引用其索引或任何其他方法进一步增强它。
  • There is a 2nd collection ChildrenHeaders , because if you'd try to fetch Expanders from 2 sources, they would be appear only on one of the containers since an UIElement can have only one parent. 第二个集合ChildrenHeaders ,因为如果您尝试从两个源中获取扩展器,它们将仅出现在其中一个容器上,因为UIElement只能有一个父级。
  • You might also want to craft a mechanism so that when an Expander is directly manipulated, the according button in the bread crumb is toggled or not. 您可能还想制作一种机制,以便在直接操作Expander时,面包屑中的相应按钮是否切换。 Hint : a good place for this would be the PropertyChangedCallback of Children where you'd build a little more inspired relationship between a toggle button and the targeted Expander 提示:一个好的地方就是ChildrenPropertyChangedCallback ,你可以在切换按钮和目标扩展器之间建立一个更加灵感的关系

ExpanderGroup XAML part ExpanderGroup XAML部分

<UserControl x:Class="delme.ExpanderGroup"
             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:local="clr-namespace:delme"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:system="clr-namespace:System;assembly=mscorlib"
             x:Name="Root"
             d:DesignHeight="300"
             d:DesignWidth="300"
             mc:Ignorable="d">
    <Grid>
        <StackPanel>

            <ItemsControl Background="LightBlue" ItemsSource="{Binding ElementName=Root, Path=ChildrenHeaders}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel IsItemsHost="True" Orientation="Horizontal" />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate DataType="system:String">
                        <ToggleButton Width="75"
                                      Height="22"
                                      Margin="2"
                                      Click="ButtonBase_OnClick"
                                      Content="{Binding}" />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>

            <Expander x:Name="RootExpander">
                <ItemsControl Background="LightCyan" ItemsSource="{Binding ElementName=Root, Path=Children}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel IsItemsHost="True" />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
            </Expander>

        </StackPanel>
    </Grid>
</UserControl>

Nothing extraordinary here, just kept it to the bare minimum for the sake of the example. 这里没什么特别的,只是为了这个例子而保持最低限度。 You might tweak it a little more, especially re-defining the template of RootExpander as IMO that little arrow should be simply hidden for a better UX. 您可以稍微调整一下,特别是将RootExpander的模板重新定义为IMO,只需隐藏小箭头以获得更好的用户体验。 You can/should use Blend to very easily tweak its template. 您可以/应该使用Blend来轻松调整其模板。

Usage example 用法示例

<Window x:Class="delme.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:local="clr-namespace:delme"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow"
        Width="525"
        Height="350"
        mc:Ignorable="d">
    <Grid>

        <local:ExpanderGroup>
            <local:ExpanderGroup.ChildrenHeaders>
                <system:String>Expander1</system:String>
                <system:String>Expander2</system:String>
            </local:ExpanderGroup.ChildrenHeaders>
            <local:ExpanderGroup.Children>
                <Expander Header="Expander1">
                    <TextBlock Text="abcd" />
                </Expander>
                <Expander Header="Expander2">
                    <TextBlock Text="efgh" />
                </Expander>
            </local:ExpanderGroup.Children>
        </local:ExpanderGroup>

    </Grid>
</Window>

Go on and improve upon that design ! 继续改进设计!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM