自定义控件样式/触发器 [英] Custom Control Styling/Triggers

查看:85
本文介绍了自定义控件样式/触发器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个由几个按钮和几个标签组成的自定义控件,但是这些按钮应该是不可见的,只显示其中的内容。通过将它们设置为透明,可以消除边框,背景等。但是,每当我将它们悬停在MouseOver上时,默认的Windows悬停效果就会再次显示整个按钮。我已经尝试了许多有关自定义控件的指南,但最终无法弄清楚如何覆盖它。基本上,我的问题可以归结为:可以在generic.xaml文件中放置多少内容,必须在该文件中使用哪个组织,这些样式还有其他地方可用吗?我确实意识到这是一个非常基本的问题,但这只是让我发疯,无法找出具体答案。谢谢!

I'm trying to make a custom control that consists of several buttons and a couple labels, but the buttons are supposed to be invisible, showing only the content within them. I can get rid of the border, background, etc by setting them to Transparent. But whenever I MouseOver them the default windows hover effect shows the whole button again. I've tried numerous guides on custom controls, but ultimately cannot figure out how to override this. Basically my questions boil down to, how much of this can be placed in the generic.xaml file, what organization do I have to use within that file, and are there any other places that these styling should go instead? I do realize this is a very basic question, but it's just driving me nuts not being able to figure out the specific answer. Thanks!

当前xaml:

<Style TargetType="{x:Type local:TimePicker}">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="BorderBrush" Value="Transparent" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:TimePicker}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Height="{TemplateBinding Height}"
                        Width="{TemplateBinding Width}">
                    <StackPanel Orientation="Horizontal">
                        <StackPanel x:Name="PART_Root"
                                    Orientation="Horizontal"
                                    HorizontalAlignment="Center">
                            <ToggleButton x:Name="PART_HourButton"
                                          HorizontalAlignment="Center"
                                          VerticalAlignment="Center"
                                          Margin="0"
                                          Background="Transparent"
                                          BorderBrush="Transparent"
                                          BorderThickness="0"
                                          Height="{Binding ElementName=PART_IncDecPanel, Path=ActualHeight}"
                                          Width="{Binding ElementName=PART_HourButton, Path=ActualHeight}"
                                          Content="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Hour}">
                                                                    <ToggleButton.Triggers>
                                    <Trigger Property="IsMouseOver" Value="True">
                                        <Setter Property="Background" Value="Transparent" />
                                    </Trigger>
                                </ToggleButton.Triggers>
                            </ToggleButton>
                            <Label x:Name="PART_HourMinSeparator"
                                   HorizontalAlignment="Center"
                                   VerticalAlignment="Center"
                                   Margin="0"
                                   Content=":" />
                            <ToggleButton x:Name="PART_MinButton"
                                          HorizontalAlignment="Center"
                                          VerticalAlignment="Center"
                                          Margin="0"
                                          Background="Transparent"
                                          BorderBrush="Transparent"
                                          BorderThickness="0"
                                          Height="{Binding ElementName=PART_HourButton, Path=ActualHeight}"
                                          Width="{Binding ElementName=PART_HourButton, Path=ActualWidth}"
                                          Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Minute}" />
                            <StackPanel x:Name="PART_IncDecPanel" HorizontalAlignment="Center" VerticalAlignment="Center">
                                <Button x:Name="PART_IncreaseTime"
                                        Background="Transparent"
                                        BorderBrush="Transparent"
                                        BorderThickness="0"
                                        HorizontalAlignment="Center"
                                        HorizontalContentAlignment="Center"
                                        VerticalAlignment="Center"
                                        VerticalContentAlignment="Center"
                                        Margin="0"
                                        Padding="0"
                                        Width="22"
                                        Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IncreaseImage.ActualHeight}">
                                    <Image Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IncreaseImage}" />
                                </Button>
                                <Button x:Name="PART_DecreaseTime"
                                        Background="Transparent"
                                        BorderBrush="Transparent"
                                        BorderThickness="0"
                                        HorizontalContentAlignment="Center"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Center"
                                        VerticalContentAlignment="Center"
                                        Margin="0"
                                        Padding="0"
                                        Height="{Binding ElementName=PART_IncreaseTime, Path=ActualHeight}"
                                        Width="{Binding ElementName=PART_IncreaseTime, Path=ActualWidth}">
                                    <Image Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DecreaseImage}" />
                                </Button>
                            </StackPanel>
                        </StackPanel>
                    </StackPanel>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>


推荐答案

WPF使用看不见的控件,这基本上意味着您可以更改控件的整个可视部分(在设计时或运行时),而无需更改其代码或该代码的行为。您已经在使用此概念为TimePicker控件创建默认样式。如果要从该样式中删除ControlTemplate,则在运行时将看不到任何内容,因为控件本身只是C#或VB代码中定义的行为。

WPF uses "lookless controls," which basically means that you can change the entire visual part (at design- or run-time) of a control without changing its code or the behavior of that code. You're already making use of this concept to create a default Style for your TimePicker control. If you were to remove the ControlTemplate from that Style, you would see nothing at runtime because the control itself is just the behavior defined in the C# or VB code.

听起来您想保留按钮的行为,但要完全改变外观,这是重新模板化的理想方案。这是一个非常简单的示例,仅显示内容(在ContentPresenter中):

Since it sounds like you want to keep the behavior of your buttons, but completely change the look, this is an ideal scenario for re-templating. Here's a very simple example that will show only the Content (in the ContentPresenter):

<Button Content="Hello Template">
    <Button.Template>
        <ControlTemplate TargetType="{x:Type Button}">
            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </ControlTemplate>
    </Button.Template>
</Button>

您可能希望向模板中添加更多内容,例如透明边框以捕获鼠标输入并也许一些触发器。您尝试在示例中在ToggleButton上使用触发器的方式不正确(FrameworkElement Triggers集合仅适用于EventTriggers),但是在ControlTemplate或Style内,该模式将起作用。

You will probably want to add some more to the template, like a Transparent Border to catch mouse input and maybe some Triggers. The way you're attempting to use a Trigger on the ToggleButton in your example is incorrect (FrameworkElement Triggers collection only works with EventTriggers), but inside a ControlTemplate or Style, that pattern will work.

如果要将相同的样式应用于TimePicker ControlTemplate中的每个按钮,则可以向ControlTemplate的资源集合中添加默认的按钮样式:

If you want to apply the same Style to every Button inside your TimePicker ControlTemplate you can add a default Button Style to the Resources collection of your ControlTemplate:

<ControlTemplate TargetType="{x:Type MyControl}">
    <ControlTemplate.Resources>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ControlTemplate.Resources>
    ...
</ControlTemplate>

这篇关于自定义控件样式/触发器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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