简体   繁体   English

WPF扩展器模板-在ToggleButton上方显示内容

[英]WPF Expander Templating - Display Content above 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... 我将通过创建不同的模板来创建新的Expander Control(学习目的),但无法弄清楚我在做什么错...

ToggleButtonTemplate: ToggleButtonTemplate:

<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 Template: 扩展器模板:

<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>

the whole space inside the Control gets filled by the Button (the ToggleButton isn't visible anymore). 控件内的整个空间都由Button填充(ToggleButton不再可见)。

What am i doing wrong? 我究竟做错了什么?

In addition I have some questions regarding this issue: 此外,我对此问题还有一些疑问:

  1. What does "ContentSource="Content"" do? “ ContentSource =” Content“”是做什么的? What is it for? 这是为了什么 Whats different to "Content="{Templatebinding Content}""? 与“ Content =“ {Templatebinding Content}”“有什么不同?
  2. Does the Expander's Property "IsExpanded" get changed when the ToggleButtons Property "IsPressed" gets changed? 当ToggleButtons属性“ IsPressed”被更改时,扩展器的属性“ IsExpanded”是否被更改? What if there is no Togglebutton in the Expander at all? 如果扩展器中根本没有Togglebutton怎么办?

first off, consider modifying your Expander template to look something like this: 首先,请考虑将您的Expander模板修改为如下所示:

 <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. 首先,您实际上需要在扩展器中放置一些东西以确保其正常工作-我现在在此处放置一个具有固定大小的矩形。

Next, i changed the first RowDefinition to be auto instead of *, as you want the expander to actually expand when opened. 接下来,我将第一个RowDefinition更改为auto而不是*,因为您希望扩展器在打开时实际进行扩展。 (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. 自动使用的行空间恰好满足行中内容的需要,因此当折叠时,该大小将为0,而在展开时,自动将变为500以适合矩形。

The third thing i did was remove your bindings from the ContentPresenter. 我做的第三件事是从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. 碰巧的是,Windows的带有内容的模板(例如可以在其中放置其他内容的模板)将自动在其模板中查找第一个ContentPresenter / ItemsPresenter标记,并将内容推入其中。

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". 我所做的是将相对资源模板绑定到属性“ IsExpanded”。 Togglebuttons have 2 main states: "Checked" and "Unchecked" (true/false), and Expanders have 2 main states: "Expanded" and "Collapsed" (true/false). 切换按钮具有2个主要状态:“已检查”和“未检查”(是/否),而扩展器有2个主要状态:“已扩展”和“已崩溃”(是/否)。 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. 因此,基本上我所做的就是告诉ToggleButton与位于其中的父项共享其被选中或未选中状态的真/假状态。

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. 完整的绑定再次是"{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsChecked}" ,用英语本质上是说“绑定到相关源,而相关源是您在模板中的父级,并且因此绑定到所述模板的“ IsChecked”属性。

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. 最后,我更改了您的触发器,这些触发器经过很长的路要隐藏起来(试图通过减小Grid的大小来挤压它。它位于其中),而是只是告诉它在扩展器的“ IsExpanded ”(并感谢我们的绑定,ToggleButton的“ IsChecked”)设置为false,而将其设置为true则相反。

.

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. 至于您的其他问题:1)ContentSource用于为ContentPresenter提供别名/替代名称,我怀疑您很快就会需要它。 The property name is sort of misleading, i grant you. 财产名称有点误导,我同意。

2) As we saw above, no - the ToggleButton needs to be bound to the templated parent's "IsExpanded" property in order to work. 2)如上所示,否-ToggleButton必须绑定到模板化父对象的“ IsExpanded”属性才能正常工作。 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. 如果要取出按钮,则在您创建绑定或用代码指示打开/关闭之前,扩展器根本无法工作。

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

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