单击标题时防止WPF扩展器扩展

时间:2009-09-08 20:24:32

标签: wpf xaml expander

如何在单击标题时阻止WPF Expander扩展?我希望我的Expander仅在单击展开按钮时展开或折叠。

我认为答案与取消泡沫事件有关。如果可能的话,我想在XAML中实现解决方案,同时避免重新模拟整个Expander

7 个答案:

答案 0 :(得分:16)

实际上,比修改模板更简单的XAML解决方案。在这种情况下,不要使用Expander的头属性。而是使用您自己的样式TextBlock覆盖扩展器。

<Application.Resources>
    <Style x:Key="ExpanderHeader" TargetType="{x:Type TextBlock}">
        <Setter Property="Height" Value="22" />
        <Setter Property="Margin" Value="21,0,0,0" />
        <Setter Property="Padding" Value="9,3,0,0" />
        <Setter Property="HorizontalAlignment" Value="Stretch" />
        <Setter Property="VerticalAlignment" Value="Top" />
    </Style>
</Application.Resources>

<Grid>
    <Expander>
        <TextBlock Text="I am some content. I have disowned my default header." Margin="10,5" />
    </Expander>
    <TextBlock Text="I'm filling in for the default header. You'll like me better anyway."
               Style="{StaticResource ResourceKey=ExpanderHeader}"/>
</Grid>

答案 1 :(得分:4)

标题是创建事件的按钮,因此您需要更改Expander的模板,只需将扩展器图标作为按钮。

以下是how to change the expander的帖子。

答案 2 :(得分:2)

我的解决方案是将标题留空并仅标记在作为标题的控件上(使用画布进行绝对定位),这样只有图标会扩展控件:

<Grid Height="{Binding ElementName=exp, Path=ActualHeight}">
    <Canvas>
        <Expander Name="exp">
        ...
        </Expander>
        <Control Style="{StaticResource ExpanderHeaderStyle}" Margin="20,0,0,0" />
     </Canvas>
</Grid>

答案 3 :(得分:1)

我按照Simeon的建议修改了Expander控件的默认模板。

以下ControlTemplate定义了一个扩展器,它只在用户点击标题图标时作出反应(扩展/折叠)。

这很快又很脏,所以希望它会破裂。

<ControlTemplate x:Key="LazyExpanderTemplate" TargetType="Expander">
        <Border BorderThickness="{TemplateBinding Border.BorderThickness}" CornerRadius="3,3,3,3" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" SnapsToDevicePixels="True">
            <DockPanel>
                <DockPanel DockPanel.Dock="Top" Name="HeaderSite">
                    <ToggleButton 
                        DockPanel.Dock="Left"
                        IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded}"
                        Foreground="{TemplateBinding TextElement.Foreground}" 
                        FontFamily="{TemplateBinding TextElement.FontFamily}" 
                        FontSize="{TemplateBinding TextElement.FontSize}" 
                        FontStretch="{TemplateBinding TextElement.FontStretch}" 
                        FontStyle="{TemplateBinding TextElement.FontStyle}" 
                        FontWeight="{TemplateBinding TextElement.FontWeight}" 
                        HorizontalContentAlignment="{TemplateBinding Control.HorizontalContentAlignment}" 
                        VerticalContentAlignment="{TemplateBinding Control.VerticalContentAlignment}" 
                        Padding="{TemplateBinding Control.Padding}" 
                        MinWidth="0" 
                        MinHeight="0" 
                        Margin="1,1,1,1" 
                        >
                        <ToggleButton.Style>
                            <Style TargetType="ToggleButton">
                                <Setter Property="Control.Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="ToggleButton">
                                            <Border Padding="{TemplateBinding Control.Padding}">
                                                <Grid Background="#00FFFFFF" SnapsToDevicePixels="False">
                                                    <Grid.ColumnDefinitions>
                                                        <ColumnDefinition Width="19" />
                                                        <ColumnDefinition Width="*" />
                                                    </Grid.ColumnDefinitions>
                                                    <Ellipse Stroke="#FFA9A9A9" Name="circle" Width="19" Height="19" HorizontalAlignment="Center" VerticalAlignment="Center" />
                                                    <Ellipse Name="shadow" Width="17" Height="17" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden" />
                                                    <Path Data="M1,1.5L4.5,5 8,1.5" Stroke="#FF666666" StrokeThickness="2" Name="arrow" HorizontalAlignment="Center" VerticalAlignment="Center" SnapsToDevicePixels="False" />
                                                </Grid>
                                            </Border>
                                            <ControlTemplate.Triggers>
                                                <Trigger Property="ToggleButton.IsChecked" Value="True" >
                                                    <Setter Property="Path.Data" TargetName="arrow">
                                                        <Setter.Value>
                                                            <StreamGeometry>M1,4.5L4.5,1 8,4.5</StreamGeometry>
                                                        </Setter.Value>
                                                    </Setter>
                                                </Trigger>
                                                <Trigger Property="UIElement.IsMouseOver" Value="True">
                                                    <Setter Property="Shape.Stroke" TargetName="circle">
                                                        <Setter.Value>
                                                            <SolidColorBrush>#FF666666</SolidColorBrush>
                                                        </Setter.Value>
                                                    </Setter>
                                                    <Setter Property="Shape.Stroke" TargetName="arrow">
                                                        <Setter.Value>
                                                            <SolidColorBrush>#FF222222</SolidColorBrush>
                                                        </Setter.Value>
                                                    </Setter>
                                                    <Setter Property="UIElement.Visibility" TargetName="shadow">
                                                        <Setter.Value>
                                                            <x:Static Member="Visibility.Visible" />
                                                        </Setter.Value>
                                                    </Setter>
                                                </Trigger>
                                            </ControlTemplate.Triggers>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </ToggleButton.Style>
                        <ToggleButton.FocusVisualStyle>
                            <Style TargetType="IFrameworkInputElement">
                                <Setter Property="Control.Template">
                                    <Setter.Value>
                                        <ControlTemplate>
                                            <Border>
                                                <Rectangle Stroke="#FF000000" StrokeThickness="1" StrokeDashArray="1 2" Margin="0,0,0,0" SnapsToDevicePixels="True" />
                                            </Border>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </ToggleButton.FocusVisualStyle>
                    </ToggleButton>
                    <ContentPresenter
                        RecognizesAccessKey="True"
                        Content="{TemplateBinding HeaderedContentControl.Header}" 
                        ContentTemplate="{TemplateBinding HeaderedContentControl.HeaderTemplate}"
                        ContentStringFormat="{TemplateBinding HeaderedContentControl.HeaderStringFormat}"
                        Margin="4,0,0,0"
                        HorizontalAlignment="Left"
                        VerticalAlignment="Center"
                        SnapsToDevicePixels="True"
                        />
                </DockPanel>
                <ContentPresenter Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Name="ExpandSite" Margin="{TemplateBinding Control.Padding}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" Visibility="Collapsed" Focusable="False" DockPanel.Dock="Bottom" />
            </DockPanel>
        </Border>
        <ControlTemplate.Triggers>
            <Trigger Property="Expander.IsExpanded">
                <Setter Property="UIElement.Visibility" TargetName="ExpandSite">
                    <Setter.Value>
                        <x:Static Member="Visibility.Visible" />
                    </Setter.Value>
                </Setter>
                <Trigger.Value>
                    <s:Boolean>True</s:Boolean>
                </Trigger.Value>
            </Trigger>
            <Trigger Property="Expander.ExpandDirection" Value="Right">
                <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Right"/>
                <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Left"/>
                <Setter Property="FrameworkElement.Style" TargetName="HeaderSite">
                    <Setter.Value>
                        <Style TargetType="ToggleButton">
                            <Setter Property="Control.Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="ToggleButton">
                                        <Border Padding="{TemplateBinding Control.Padding}">
                                            <Grid Background="#00FFFFFF" SnapsToDevicePixels="False">
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="19" />
                                                    <RowDefinition Height="*" />
                                                </Grid.RowDefinitions>
                                                <Grid>
                                                    <Grid.LayoutTransform>
                                                        <TransformGroup>
                                                            <TransformGroup.Children>
                                                                <RotateTransform Angle="-90" />
                                                            </TransformGroup.Children>
                                                        </TransformGroup>
                                                    </Grid.LayoutTransform>
                                                    <Ellipse Stroke="#FFA9A9A9" Name="circle" Width="19" Height="19" HorizontalAlignment="Center" VerticalAlignment="Center" />
                                                    <Ellipse Name="shadow" Width="17" Height="17" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden" />
                                                    <Path Data="M1,1.5L4.5,5 8,1.5" Stroke="#FF666666" StrokeThickness="2" Name="arrow" HorizontalAlignment="Center" VerticalAlignment="Center" SnapsToDevicePixels="False" />
                                                </Grid>
                                                <ContentPresenter RecognizesAccessKey="True" Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Margin="0,4,0,0" HorizontalAlignment="Center" VerticalAlignment="Top" SnapsToDevicePixels="True" Grid.Row="1" />
                                            </Grid>
                                        </Border>
                                        <ControlTemplate.Triggers>
                                            <Trigger Property="ToggleButton.IsChecked">
                                                <Setter Property="Path.Data" TargetName="arrow">
                                                    <Setter.Value>
                                                        <StreamGeometry>M1,4.5L4.5,1 8,4.5</StreamGeometry>
                                                    </Setter.Value>
                                                </Setter>
                                                <Trigger.Value>
                                                    <s:Boolean>True</s:Boolean>
                                                </Trigger.Value>
                                            </Trigger>
                                            <Trigger Property="UIElement.IsMouseOver">
                                                <Setter Property="Shape.Stroke" TargetName="circle">
                                                    <Setter.Value>
                                                        <SolidColorBrush>#FF666666</SolidColorBrush>
                                                    </Setter.Value>
                                                </Setter>
                                                <Setter Property="Shape.Stroke" TargetName="arrow">
                                                    <Setter.Value>
                                                        <SolidColorBrush>#FF222222</SolidColorBrush>
                                                    </Setter.Value>
                                                </Setter>
                                                <Setter Property="UIElement.Visibility" TargetName="shadow">
                                                    <Setter.Value>
                                                        <x:Static Member="Visibility.Visible" />
                                                    </Setter.Value>
                                                </Setter>
                                                <Trigger.Value>
                                                    <s:Boolean>True</s:Boolean>
                                                </Trigger.Value>
                                            </Trigger>
                                        </ControlTemplate.Triggers>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <Trigger Property="Expander.ExpandDirection">
                <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Top"/>
                <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Bottom"/>
                <Setter Property="FrameworkElement.Style" TargetName="HeaderSite">
                    <Setter.Value>
                        <Style TargetType="ToggleButton">
                            <Setter Property="Control.Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="ToggleButton">
                                        <Border Padding="{TemplateBinding Control.Padding}">
                                            <Grid Background="#00FFFFFF" SnapsToDevicePixels="False">
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="19" />
                                                    <ColumnDefinition Width="*" />
                                                </Grid.ColumnDefinitions>
                                                <Grid>
                                                    <Grid.LayoutTransform>
                                                        <TransformGroup>
                                                            <TransformGroup.Children>
                                                                <RotateTransform Angle="180" />
                                                            </TransformGroup.Children>
                                                        </TransformGroup>
                                                    </Grid.LayoutTransform>
                                                    <Ellipse Stroke="#FFA9A9A9" Name="circle" Width="19" Height="19" HorizontalAlignment="Center" VerticalAlignment="Center" />
                                                    <Ellipse Name="shadow" Width="17" Height="17" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden" />
                                                    <Path Data="M1,1.5L4.5,5 8,1.5" Stroke="#FF666666" StrokeThickness="2" Name="arrow" HorizontalAlignment="Center" VerticalAlignment="Center" SnapsToDevicePixels="False" />
                                                </Grid>
                                                <ContentPresenter RecognizesAccessKey="True" Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Margin="4,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" SnapsToDevicePixels="True" Grid.Column="1" />
                                            </Grid>
                                        </Border>
                                        <ControlTemplate.Triggers>
                                            <Trigger Property="ToggleButton.IsChecked">
                                                <Setter Property="Path.Data" TargetName="arrow">
                                                    <Setter.Value>
                                                        <StreamGeometry>M1,4.5L4.5,1 8,4.5</StreamGeometry>
                                                    </Setter.Value>
                                                </Setter>
                                                <Trigger.Value>
                                                    <s:Boolean>True</s:Boolean>
                                                </Trigger.Value>
                                            </Trigger>
                                            <Trigger Property="UIElement.IsMouseOver">
                                                <Setter Property="Shape.Stroke" TargetName="circle">
                                                    <Setter.Value>
                                                        <SolidColorBrush>#FF666666</SolidColorBrush>
                                                    </Setter.Value>
                                                </Setter>
                                                <Setter Property="Shape.Stroke" TargetName="arrow">
                                                    <Setter.Value>
                                                        <SolidColorBrush>#FF222222</SolidColorBrush>
                                                    </Setter.Value>
                                                </Setter>
                                                <Setter Property="UIElement.Visibility" TargetName="shadow">
                                                    <Setter.Value>
                                                        <x:Static Member="Visibility.Visible" />
                                                    </Setter.Value>
                                                </Setter>
                                                <Trigger.Value>
                                                    <s:Boolean>True</s:Boolean>
                                                </Trigger.Value>
                                            </Trigger>
                                        </ControlTemplate.Triggers>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </Setter.Value>
                </Setter>
                <Trigger.Value>
                    <x:Static Member="ExpandDirection.Up" />
                </Trigger.Value>
            </Trigger>
            <Trigger Property="Expander.ExpandDirection">
                <Setter Property="DockPanel.Dock" TargetName="ExpandSite">
                    <Setter.Value>
                        <x:Static Member="Dock.Left" />
                    </Setter.Value>
                </Setter>
                <Setter Property="DockPanel.Dock" TargetName="HeaderSite">
                    <Setter.Value>
                        <x:Static Member="Dock.Right" />
                    </Setter.Value>
                </Setter>
                <Setter Property="FrameworkElement.Style" TargetName="HeaderSite">
                    <Setter.Value>
                        <Style TargetType="ToggleButton">
                            <Setter Property="Control.Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="ToggleButton">
                                        <Border Padding="{TemplateBinding Control.Padding}">
                                            <Grid Background="#00FFFFFF" SnapsToDevicePixels="False">
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="19" />
                                                    <RowDefinition Height="*" />
                                                </Grid.RowDefinitions>
                                                <Grid>
                                                    <Grid.LayoutTransform>
                                                        <TransformGroup>
                                                            <TransformGroup.Children>
                                                                <RotateTransform Angle="90" />
                                                            </TransformGroup.Children>
                                                        </TransformGroup>
                                                    </Grid.LayoutTransform>
                                                    <Ellipse Stroke="#FFA9A9A9" Name="circle" Width="19" Height="19" HorizontalAlignment="Center" VerticalAlignment="Center" />
                                                    <Ellipse Name="shadow" Width="17" Height="17" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden" />
                                                    <Path Data="M1,1.5L4.5,5 8,1.5" Stroke="#FF666666" StrokeThickness="2" Name="arrow" HorizontalAlignment="Center" VerticalAlignment="Center" SnapsToDevicePixels="False" />
                                                </Grid>
                                                <ContentPresenter RecognizesAccessKey="True" Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Margin="0,4,0,0" HorizontalAlignment="Center" VerticalAlignment="Top" SnapsToDevicePixels="True" Grid.Row="1" />
                                            </Grid>
                                        </Border>
                                        <ControlTemplate.Triggers>
                                            <Trigger Property="ToggleButton.IsChecked">
                                                <Setter Property="Path.Data" TargetName="arrow">
                                                    <Setter.Value>
                                                        <StreamGeometry>M1,4.5L4.5,1 8,4.5</StreamGeometry>
                                                    </Setter.Value>
                                                </Setter>
                                                <Trigger.Value>
                                                    <s:Boolean>True</s:Boolean>
                                                </Trigger.Value>
                                            </Trigger>
                                            <Trigger Property="UIElement.IsMouseOver">
                                                <Setter Property="Shape.Stroke" TargetName="circle">
                                                    <Setter.Value>
                                                        <SolidColorBrush>#FF666666</SolidColorBrush>
                                                    </Setter.Value>
                                                </Setter>
                                                <Setter Property="Shape.Stroke" TargetName="arrow">
                                                    <Setter.Value>
                                                        <SolidColorBrush>#FF222222</SolidColorBrush>
                                                    </Setter.Value>
                                                </Setter>
                                                <Setter Property="UIElement.Visibility" TargetName="shadow">
                                                    <Setter.Value>
                                                        <x:Static Member="Visibility.Visible" />
                                                    </Setter.Value>
                                                </Setter>
                                                <Trigger.Value>
                                                    <s:Boolean>True</s:Boolean>
                                                </Trigger.Value>
                                            </Trigger>
                                        </ControlTemplate.Triggers>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </Setter.Value>
                </Setter>
                <Trigger.Value>
                    <x:Static Member="ExpandDirection.Left" />
                </Trigger.Value>
            </Trigger>
            <Trigger Property="UIElement.IsEnabled">
                <Setter Property="TextElement.Foreground">
                    <Setter.Value>
                        <DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
                    </Setter.Value>
                </Setter>
                <Trigger.Value>
                    <s:Boolean>False</s:Boolean>
                </Trigger.Value>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

答案 4 :(得分:1)

一个相当简单的解决方案是按以下方式修改Expander控件tempate使用的切换按钮模板。

  • 将网格和边框的背景设置为{x:Null}
  • 将内容展示者IsHitTestVisible设置为False

            <ControlTemplate TargetType="{x:Type ToggleButton}">
            <Border Padding="{TemplateBinding Padding}" Background="{x:Null}">
                <Grid Background="{x:Null}" 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" HorizontalAlignment="Center" Height="19" Stroke="DarkGray" 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="#666" StrokeThickness="2" VerticalAlignment="Center"/>
                    </Grid>
                    <ContentPresenter HorizontalAlignment="Center" Margin="0,4,0,0" Grid.Row="1" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Top"IsHitTestVisible="False"/>
                </Grid>
            </Border>
        </ControlTemplate>
    

答案 5 :(得分:0)

您可以将IsEnabled设置为false,但是如果您需要确定在单击标题时是否可以展开或折叠:

public class MyExpander : Expander
{
    private bool CanExpand() => true;

    private bool CanCollapse() => true;

    private bool rollback;

    protected override void OnExpanded()
    {
        if (rollback) return;
        if (CanExpand())
        {
            base.OnExpanded();
        }
        else
        {
            rollback = true;
            SetCurrentValue(IsExpandedProperty, false);
            rollback = false;
        }
    }

    protected override void OnCollapsed()
    {
        if (rollback) return;
        if (CanCollapse())
        {
            base.OnCollapsed();
        }
        else
        {
            rollback = true;
            SetCurrentValue(IsExpandedProperty, true);
            rollback = false;
        }
    }
}

答案 6 :(得分:0)

正如我刚刚检查过的,标题被命名为“ HeaderSite”。您可以使用类似描述的in this post的方法来按名称查找子级。当您有了孩子时,您只需更改其可见性即可。还要确保已加载扩展器,否则您将看不到孩子。

expander.Loaded += (s, e) => {
    var hv = expander.findChildByName("HeaderSite");
    if (hv == null) return;
    hv.Visibility = Visibility.Collapsed;
};

我想这不能保证名称不会更改,对我来说,这只是表面上的问题。