WPF 扩展器模板 - 在 ToggleButton 上方显示内容 [英] WPF Expander Templating - Display Content above ToggleButton

查看:35
本文介绍了WPF 扩展器模板 - 在 ToggleButton 上方显示内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我即将通过创建不同的模板来创建一个新的扩展控件(学习目的),但无法弄清楚我做错了什么......

I'm about to create a new Expander Control (learning purpose) by creating different templates but can't figure out what I'm doing wrong...

切换按钮模板:

<ToggleButton>
    <ToggleButton.Template>
        <ControlTemplate TargetType="ToggleButton">
            <Border x:Name="eBB" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                <Grid>
                    <Path x:Name="Sign" Data="M 0,10 L 7.5,2.5 L 15, 10" Stroke="Black" Width="15">
                        <Path.RenderTransform>
                            <RotateTransform Angle="0"/>
                        </Path.RenderTransform>
                    </Path>
                </Grid>
            </Border>
            <ControlTemplate.Triggers>
                <Trigger Property="IsChecked" Value="True">
                    <Setter Property="Data" TargetName="Sign" Value="M 0,2.5 L 7.5,10 L 15,2.5"/>
                </Trigger>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Stroke" Value="#222" TargetName="Sign"/>
                    <Setter Property="Background" Value="#666" TargetName="eBB"/>
                </Trigger>
                <Trigger Property="IsPressed" Value="True">
                    <Setter Property="Stroke" Value="#FF003366" TargetName="Sign"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </ToggleButton.Template>
</ToggleButton>

扩展模板:

<Expander>
    <Expander.Template>
        <ControlTemplate TargetType="Expander">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition x:Name="ContentRow" Height="*"/>
                    <RowDefinition Height="20"/>
                </Grid.RowDefinitions>
                <ContentPresenter Grid.Row="0" Visibility="Collapsed" Content="{TemplateBinding Content}"/>
                <local:FullSizeExpanderToggleButton Grid.Row="1" />
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="IsExpanded" Value="True">
                    <Setter Property="Visibility" Value="Visible"/>
                    <Setter Property="Height" Value="*" TargetName="ContentRow"/>
                </Trigger>
                <Trigger Property="IsExpanded" Value="False">
                    <Setter Property="Height" Value="0" TargetName="ContentRow"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Expander.Template>
</Expander>

现在,当我想在主视图中添加扩展器时:

Now when I want to add the Expander in my Main View:

<custom:FullSizeExpander Width="300">
            <Button/>
        </custom:FullSizeExpander>

Control 内的整个空间都被 Button 填满(ToggleButton 不再可见).

the whole space inside the Control gets filled by the Button (the ToggleButton isn't visible anymore).

我做错了什么?

此外,我对这个问题还有一些疑问:

In addition I have some questions regarding this issue:

  1. ContentSource="Content"" 有什么作用?它是做什么用的?与Content="{Templatebinding Content}""有何不同?
  2. 当 ToggleButtons 属性IsPressed"更改时,扩展器的属性IsExpanded"是否会更改?如果扩展器中根本没有切换按钮怎么办?

推荐答案

首先,考虑将您的 Expander 模板修改为如下所示:

first off, consider modifying your Expander template to look something like this:

 <Expander>
            <Rectangle Height="500" Width="500" Fill="Red"/>
            <Expander.Template>
                <ControlTemplate TargetType="Expander">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="20"/>
                        </Grid.RowDefinitions>
                        <ContentPresenter Grid.Row="0" x:Name="ContentPresenter"/>
                        <ToggleButton Grid.Row="1" IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsExpanded" Value="True">
                            <Setter TargetName="ContentPresenter" Property="Visibility" Value="Visible"/>
                        </Trigger>
                        <Trigger Property="IsExpanded" Value="False">
                            <Setter TargetName="ContentPresenter" Property="Visibility" Value="Collapsed"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Expander.Template>
        </Expander>

我将解释它是如何工作的,以及为什么它以前自上而下不起作用.首先,您需要在扩展器中实际放置一些东西以确保它正常工作 - 我现在在这里放置了一个固定大小的矩形.

I'll explain how it works, and why it wasn't working before from the top-down. First off, you'll want to actually put something in the expander to make sure it's working - i put a rectangle here with fixed sizes for now.

接下来,我将第一个 RowDefinition 更改为 auto 而不是 *,因为您希望扩展器在打开时实际展开.(而不仅仅是将其内容隐藏在一个大的空白区域中).Auto 使用的空间与行中内容所需的空间完全一样,因此当它折叠时,该大小将为 0,当它展开时,auto 将变为 500 以适合矩形.

Next, i changed the first RowDefinition to be auto instead of *, as you want the expander to actually expand when opened. (rather than just hide its content in a big empty area). Auto uses exactly as much space as the content in the row needs, so when it's collapsed, that size will be 0, and when it's expanded, auto will become 500 to fit the rectangle.

我做的第三件事是从 ContentPresenter 中删除您的绑定.碰巧的是,Windows 的内容承载模板(如任何可以在其中放置其他内容的模板)将自动查找其模板中的第一个 ContentPresenter/ItemsPresenter 标记并将内容推入其中.

The third thing i did was remove your bindings from the ContentPresenter. As it happens, Windows' content-bearing templates (as in anything that can have something else placed inside of it) will automatically look for the first ContentPresenter / ItemsPresenter tag inside its template and shove content into it.

然而,至于切换按钮(我保持简单并将其保留为标准切换按钮),这个确实需要绑定.我所做的是一个到属性IsExpanded"的Relativesource Templatebinding.切换按钮有两种主要状态:选中"和未选中"(真/假),扩展器有两种主要状态:展开"和折叠"(真/假).所以基本上我所做的就是告诉 ToggleButton 与它所在的父级共享其被选中或未选中的真/假状态.

As for the togglebutton however (i kept it simple and left it as a standard togglebutton), this one does actually need a binding. What i did was a Relativesource Templatebinding to the property "IsExpanded". Togglebuttons have 2 main states: "Checked" and "Unchecked" (true/false), and Expanders have 2 main states: "Expanded" and "Collapsed" (true/false). So essentially all i did was tell the ToggleButton to share its true/false state of being checked or unchecked with the parent it sits inside of.

再次完全绑定是"{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsChecked}",在英文中本质上是说绑定到一个相关的源,而相关的源是父你在模板中,并将其绑定到所述模板;sIsChecked"属性.

The full binding again is "{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsChecked}", which in english is essentially saying "Bind to a related source, and the related source is the parent you're in the template of, and bind so to said template;s "IsChecked" property.

最后,我更改了您的触发器,这些触发器使 ContentPresenter 隐藏起来(试图通过减小它所在的 Grid.Row 的大小来压缩它),而是告诉它在expander 的IsExpanded"(由于我们的绑定,ToggleButton 的IsChecked")被设置为 false,而当它们被设置为 true 时则相反.

Lastly i changed your triggers which were going the long way around to get the ContentPresenter to become hidden (trying to squash it by reducing the size of the Grid.Row it sits in), and instead just told it to hide when the expander's "IsExpanded" (and thanks to our binding, the ToggleButton's "IsChecked") is set to false, and the opposite when they're set to true.

.

至于您的其他问题:1) ContentSource 用于为 ContentPresenter 提供别名/替代名称,我怀疑您很快就会需要它.属性名称有点误导,我承认.

As for your other questions: 1) The ContentSource is used to give the ContentPresenter an alias/alternate name, and i doubt you'll need it anytime soon. The property name is sort of misleading, i grant you.

2) 正如我们在上面看到的,不 - ToggleButton 需要绑定到模板化父级的IsExpanded"属性才能工作.如果您要取出按钮,则在您创建绑定或在代码中发出指令来告诉它打开/关闭之前,扩展器根本不会工作.

2) As we saw above, no - the ToggleButton needs to be bound to the templated parent's "IsExpanded" property in order to work. If you were to take the button out, the Expander simply would not work until you created a binding or made an instruction in code to tell it to open/close.

这篇关于WPF 扩展器模板 - 在 ToggleButton 上方显示内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆