【问题标题】:Changing the Content Template of a custom control when a property changes属性更改时更改自定义控件的内容模板
【发布时间】:2011-07-18 20:00:26
【问题描述】:

我对 WPF 还很陌生,我不确定如何做我想做的事情。

我构建了一个自定义控件,我称之为音量控件。它有 2 个重复按钮,1 个用于增加 Volume 属性的值,1 个用于减小它,以及一个 ProgressBar,用于提供当前 Volume 的可视化表示。该控件有一个名为“Orientation”的类型为 Orientation 的属性。当它是水平时,我希望控件以一种方式绘制,而当它是垂直时,我希望它看起来不同。

在水平模式下,控件将简单地将 3 个控件放在水平 StackPanel 中。 Vertical 的外观有点复杂,因为它有一个 Grid,它有 2 列和 2 行。 2 个重复按钮在左侧堆叠在一起,而 ProgressBar 跨越两行并位于右侧。

我似乎无法弄清楚如何根据 Orientation 属性的值使控件更改其外观。到目前为止,这是我所得到的:

<Style x:Key="Horizontal" TargetType="{x:Type cs:VolumeControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type cs:VolumeControl}">
                <StackPanel Orientation="Horizontal">
                    ...
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="Vertical" TargetType="{x:Type cs:VolumeControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type cs:VolumeControl}">
                <Grid>
                    ...
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我知道我需要这样的东西来定义默认模板和 Orientation 属性的必要触发器:

<Style TargetType="{x:Type cs:VolumeControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type cs:VolumeControl}">
                <ControlTemplate.Triggers>
                    <Trigger Property="Orientation" Value="Horizontal">
                        ???
                    </Trigger>

                    <Trigger Property="Orientation" Value="Vertical">
                        ???
                    </Trigger>

                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
        </Setter.Value>
    </Setter>
</Style>

我不知道要在两个 Trigger 标签中添加什么才能使其正常工作。或者即使我做对了。

我查看了 ProgressBar 的模板,当 Orientation 设置为 Vertical 时,它使用 RotationTransform 垂直绘制控件。我不能这样做,因为目的是在不同的布局中绘制控件。

感谢任何帮助。

托尼

【问题讨论】:

    标签: wpf custom-controls controltemplate


    【解决方案1】:

    创建 2 个控件模板

    <ControlTemplate x:Key="Horizontal" TargetType={x:Type cs:VolumeControl}....
    <ControlTemplate x:Key="Vertical" TargetType={x:Type cs:VolumeControl}...
    

    然后创建一个样式并使用它通过触发器来切换模板

    <Style TargetType={x:Type cs:VolumeControl}>
    <Style.Triggers>
       <Trigger Property="Orientation" Value="Horizontal">
          <Setter Property="Template" Value={StaticResource Horizontal}" />
       </Trigger>
       <Trigger Property="Orientation" Value="Vertical">
          <Setter Property="Template" Value={StaticResource Vertical}" />
       </Trigger>
    </Style.Triggers>
    </Style>
    

    对我来说就像一个魅力:)

    【讨论】:

    • 谢谢!!!我已经从这里开始,因为我不需要垂直控制,但现在我知道该怎么做了。
    • 没问题。如果您尝试在控件中创建某些行为,则有时值得查看以类似方式行为的现有控件的模板(在本例中为滑块)。您可以在 Blend 中执行此操作,或使用样式窥探应用程序(大量免费或足够容易构建)。
    【解决方案2】:

    这样嵌套样式可能行不通。您可以使用 ContentControl,如下所示:

    <Style TargetType="{x:Type cs:VolumeControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type cs:VolumeControl}">
                    <ContentControl>
                        <ContentControl.Style>
                            <Style TargetType="{x:Type ContentControl}">
                                <Setter Property="ContentTemplate">
                                    <Setter.Value>
                                        <!-- Horizontal Template Here -->
                                    </Setter.Value>
                                </Setter>
                                <Style.Triggers>
                                    <DataTrigger Binding="{TemplateBinding Orientation}" Value="Vertical">
                                        <Setter Property="ContentTemplate">
                                            <Setter.Value>
                                                <!-- Vertical Template Here -->
                                            </Setter.Value>
                                        </Setter>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </ContentControl.Style>
                    </ContentControl>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    但是我不确定这是否可行,以及它是否真的是一个好主意。

    【讨论】:

    • 感谢您的回复。我尝试了自己的方式,为第一组插入“" ???在我原来的问题和垂直风格的类似声明中。那没有用。我收到一条错误消息,显示“无法在当前元素的模板中设置‘模板’属性。”然后我尝试了你的方法,我得到了一个不同的错误。我知道我可以在后面的代码中做到这一点。也许我必须这样做?
    • 我回去尝试按照你的方式去做。我得到的错误是:无法将“System.Windows.TemplateBindingExpression”类型的对象转换为“System.Windows.Data.BindingBase”。
    • 我决定放弃不断变化的方向并坚持使用水平控件,因为现在这已经足够了。如果将来我需要在窗口中进行垂直控制,我将在该窗口的资源中创建一个样式并使用它来代替。
    猜你喜欢
    • 2022-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多