简体   繁体   English

如何公开内部控件的样式?

[英]How to expose internal control for styling?

The problem seems easy: I have a UserControl , my control contains a Button . 问题似乎很简单:我有一个UserControl ,我的控件包含一个Button

Button elements can be styled. Button元素可以设置样式。 But I don't want to have style definitions in my control. 但我不希望在我的控制中有样式定义。 My control doesn't even have XAML. 我的控件甚至没有XAML。 All I want to set style like this in XAML: 我只想在XAML中设置这样的样式:

<Style TargetType="local:MyControl">
    <Setter Property="ItsButton.Padding" Value="8" />
</Style>

It doesn't work that way. 它不起作用。 How does it work? 它是如何工作的? I know I can bind any internal control's properties to my UserControl dependency properties and it will work. 我知道我可以将任何内部控件的属性绑定到我的UserControl依赖项属性,它将工作。 However it's overkill to bind many properties, does it really require so much coding to do the simple thing, or is it an easier / quicker / simpler way? 然而,绑定许多属性是不合适的,它真的需要这么多编码来做简单的事情,还是更容易/更快/更简单的方式?

BTW, it doesn't look like an overkill to you, imagine I have many internal controls like button, let's say InputBox es and such. 顺便说一句,它对你来说看起来不像是一种矫枉过正,想象一下我有许多内部控件,比如按钮,让我们说InputBox es等等。

Here's the example control code: 这是示例控制代码:

class Installable : UserControl {

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
        "Value",
        typeof(object),
        typeof(Installable),
        new FrameworkPropertyMetadata(OnValueChanged));

    public static readonly DependencyProperty InstallButtonProperty = DependencyProperty.Register(
        "InstallButton",
        typeof(Button),
        typeof(Installable),
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None));

    public static readonly DependencyProperty InstallTextProperty = DependencyProperty.Register(
        "InstallText",
        typeof(string),
        typeof(Installable),
        new FrameworkPropertyMetadata(OnInstallTextChanged));

    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
        "Command",
        typeof(ICommand),
        typeof(Installable),
        new FrameworkPropertyMetadata(OnCommandChanged));

    public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register(
        "CommandParameter",
        typeof(object),
        typeof(Installable),
        new FrameworkPropertyMetadata(OnCommandParameterChanged));

    public object Value {
        get => GetValue(ValueProperty);
        set => SetValue(ValueProperty, value);
    }

    public Button InstallButton {
        get => (Button)GetValue(InstallButtonProperty);
        set => SetValue(InstallButtonProperty, value);
    }

    public string InstallText {
        get => (string)GetValue(InstallTextProperty);
        set => SetValue(InstallTextProperty, value);
    }

    public ICommand Command {
        get => (ICommand)GetValue(CommandProperty);
        set => SetValue(CommandProperty, value);
    }

    public object CommandParameter {
        get => GetValue(CommandParameterProperty);
        set => SetValue(CommandParameterProperty, value);
    }


    public Installable() {
        InstallButton = new Button();
        Content = Value ?? InstallButton;
        InstallText = "Install";
    }

    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        var control = d as Installable;
        var value = e.NewValue;
        control.Content = value ?? control.InstallButton;
    }

    private static void OnInstallTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        var control = d as Installable;
        var text = e.NewValue as string;
        control.InstallButton.Content = text;
    }


    private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        var control = d as Installable;
        var command = e.NewValue as ICommand;
        control.InstallButton.Command = command;
    }

    private static void OnCommandParameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        var control = d as Installable;
        var value = e.NewValue;
        control.InstallButton.CommandParameter = value;
    }

}

The control displays its Value when not null, InstallButton otherwise. 控件在非空时显示其Value ,否则显示InstallButton Like if value unset - it contains button, when value set - contains value. 就像值unset一样 - 它包含按钮,当值设置 - 包含值时。 The control works like charm, but when I set the Button style in MainWindow XAML, it doesn't affect the button within my UserControl . 该控件的工作方式类似于charm,但是当我在MainWindow XAML中设置Button样式时,它不会影响UserControl的按钮。

Maybe my Button could somehow inherit style from Button style defined in MainWindow XAML? 也许我的Button可以以某种方式从MainWindow XAML中定义的Button样式继承样式?

The control Style may define a default Button Style in its Resources, which will automatically be applied to all of the control's Button child elements. 控件Style可以在其Resources中定义一个默认的Button Style,它将自动应用于所有控件的Button子元素。

<Style TargetType="local:MyControl">
    <Style.Resources>
        <Style TargetType="Button">
            <Setter Property="Margin" Value="8"/>
        </Style>
    </Style.Resources>
</Style>

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

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