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

时间:2019-07-24 08:59:04

标签: c# wpf xaml

问题似乎很简单: 我有一个UserControl,我的控件包含一个Button

可以设置

Button元素的样式。但是我不想在控件中包含样式定义。我的控件甚至没有XAML。我想要在XAML中设置这样的样式:

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

这种方式行不通。它是如何工作的? 我知道我可以将任何内部控件的属性绑定到我的UserControl依赖项属性,并且它将起作用。但是,绑定许多属性实在是太过分了,要做一件简单的事情真的需要太多的编码,还是更容易/更快/更简单的方法?

顺便说一句,这对您来说似乎并不过分,想像一下我有许多内部控件,例如按钮,比如InputBox等。

这是示例控制代码:

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

}

该控件在不为空时显示其Value,否则显示InstallButton。 就像值未设置-包含按钮,值设置-包含值一样。该控件的工作原理类似于魅力,但是当我在Button XAML中设置MainWindow样式时,它不会影响UserControl中的按钮。

也许我的Button可以从Button XAML中定义的MainWindow样式继承样式吗?

1 个答案:

答案 0 :(得分:3)

控件样式可以在其资源中定义默认的按钮样式,该样式将自动应用于控件的所有Button子元素。

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