【问题标题】:WPF ContentPresenter overrides othe Controls on the same levelWPF ContentPresenter 覆盖同一级别的其他控件
【发布时间】:2016-04-27 16:47:45
【问题描述】:

在我的上一个问题中,我将重新创建一个扩展器 + 它是切换按钮。

扩展模板:

<ControlTemplate TargetType="Expander">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="15"/>
        </Grid.RowDefinitions>
        <ContentPresenter x:Name="ContentPresenter" Grid.Row="0"/>
        <ToggleButton Grid.Row="1" >
           ....
        </ToggleButton>
    </Grid>

现在,当我在主视图中使用此自定义控件并添加控件(例如按钮)时:

<custom:FullWidthExpander Width="200" HeaderBackground="Gray">
    <Button />
</custom:FullWidthExpander>

ToggleButton(在我上面的扩展模板中定义)被此按钮覆盖。

【问题讨论】:

  • 你确定被覆盖而不是被按钮隐藏了吗?您可以使用Snoop 准确查看控件在加载和运行时的样子。
  • 是的,当窥探我的应用程序时,除了 ContentPresenter 之外的所有内容都丢失了:/
  • 如果你给你的按钮设置一个尺寸,它还会出现吗?按钮采用所有可用尺寸,因此 Auto 可能是您的 Expander 尺寸
  • 您的ControlTemplate 在哪里定义?我可以安全地假设FullWidthExpander 是自定义UserControl 吗?我在 MainWindow 中的 XAML 中使用普通 Expander 进行了快速测试,它工作得很好,所以我猜你的问题与你的控制层次结构有关。

标签: wpf xaml togglebutton templating expander


【解决方案1】:

当你这样做时,这意味着用户控件的全部内容都被你提供的内容所替换。

<custom:FullWidthExpander Width="200" HeaderBackground="Gray">
    <Button />
</custom:FullWidthExpander>

要解决这个问题,您需要在用户控件中以稍微不同的方式托管内容

首先为用户控件添加一个依赖属性

    public object UserControlContent
    {
        get { return (object)GetValue(UserControlContentProperty); }
        set { SetValue(UserControlContentProperty, value); }
    }

    public static readonly DependencyProperty UserControlContentProperty =
        DependencyProperty.Register("UserControlContent", typeof(object), typeof(FullWidthExpander),
          new PropertyMetadata(null));

然后将它绑定到用户控件的 xaml 中的 contentpresenter 并为您的用户控件定义一个名称,例如 x:Name="Root"。

<Expander Header="My expander header">
    <Expander.Template>
        <ControlTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="15"/>
                </Grid.RowDefinitions>

                <ContentPresenter x:Name="ContentPresenter" Grid.Row="0" Content="{Binding UserControlContent, ElementName=Root}" />

                <ToggleButton Grid.Row="1" Content="Togglebutton">

                </ToggleButton>
            </Grid>
        </ControlTemplate>
    </Expander.Template>
</Expander>

最后你在 maindwindow xaml 中定义内容内容

<custom:FullWidthExpander>
    <custom:FullWidthExpander.UserControlContent>
        <Button Content="Click me"/>
    </custom:FullWidthExpander.UserControlContent>
</custom:FullWidthExpander>

【讨论】:

  • 感谢您的回答 - 但我认为 ContentPresenter 是我提供的内容的某种“占位符”?
  • 对于模板是,用户控件没有。
  • @JanneMatikainen 他从未说过任何关于 UserControl 的事
  • @nkoniishvt 那是我的错——扩展器当然是一个用户控件。 (认为​​这很明显,因为我说我要创建一个新的扩展器)。因此,如果我在主视图中将 Expander 的设计定义为具有上述 ContentPresenter 的样式/模板,它会起作用吗?
  • @Chill-X 当您可以直接定义它应该如何出现在 UserControl 的 .xaml 中时,我不明白为什么您需要为 UserControl 使用 ControlTemplate。 ControlTemplate (通常)用于 CustomControl,而不是 UserControl
【解决方案2】:

您是否将UserControl.Content 绑定到Expander.Content 属性?

<!-- define a custom Template for the UserControl FullWidthExpander -->
<UserControl.Template>
    <ControlTemplate TargetType="UserControl">
        <!-- be sure to include the Content binding to pass the UC.Content to Expander -->
        <Expander Content="{TemplateBinding Content}">
            <!-- create a custom Template for this Expander -->
            <Expander.Template>
                <ControlTemplate TargetType="Expander">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition x:Name="ContentRow" Height="*"/>
                            <RowDefinition Height="20"/>
                        </Grid.RowDefinitions>
                        <ContentPresenter Grid.Row="0" Content="{TemplateBinding Content}"/>
                        <ToggleButton Grid.Row="1" Content="Test Toggle Button" />
                    </Grid>
                </ControlTemplate>
            </Expander.Template>
        </Expander>
    </ControlTemplate>
</UserControl.Template>

我做了一个快速测试,当使用这样的控件时效果很好:

<local:FullWidthExpander>
    <Button Content="Test Content Button"/>
</local:FullWidthExpander>

我还查看了your other question,如果您在此处有您的ControlTemplate.Triggers,那么您还需要确保将Expander.IsExpanded 设置为True 以查看您的内容。如果IsExpanded=False,您的触发器将隐藏顶部内容行,这是扩展器的默认设置。

【讨论】:

  • 感谢您的回复 :) - 如果我做对了,这个解决方案“只是一个肮脏的解决方法”。澄清一下,我只是想制作一个具有“新外观和感觉”的可重复使用的扩展器。你可以告诉我什么是最佳实践解决方案? (我不想通过说这是一种解决方法来侮辱你——但据我所知,用户控件对我的目的来说并不是最好的)
  • @Chill-X 在您的情况下,是的,为您的 Expander 使用自定义模板可能比使用全新的 UserControl 更好,但是无论如何核心问题都是相同的。很高兴知道原因和解决方案,这样您以后就不会遇到这样的问题:)
猜你喜欢
  • 2011-12-26
  • 2014-03-28
  • 1970-01-01
  • 1970-01-01
  • 2017-03-08
  • 2011-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多