【问题标题】:How to expose internal control for styling?如何公开样式的内部控制?
【发布时间】:2019-07-24 08:59:04
【问题描述】:

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

Button 元素可以设置样式。但我不想在我的控制中拥有样式定义。我的控件甚至没有 XAML。我想在 XAML 中设置这样的样式:

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

这样不行。它是如何工作的? 我知道我可以将任何内部控件的属性绑定到我的 UserControl 依赖属性,它会起作用。但是绑定很多属性有点矫枉过正,做简单的事情真的需要这么多的编码,还是更容易/更快/更简单的方法?

顺便说一句,这对你来说看起来并不过分,想象一下我有很多内部控件,比如按钮,比如说InputBoxes 等等。

这是示例控制代码:

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。 就像如果值未设置 - 它包含按钮,当值设置时 - 包含值。该控件的作用就像魅力一样,但是当我在MainWindow XAML 中设置Button 样式时,它不会影响我的UserControl 中的按钮。

也许我的Button 可以以某种方式继承ButtonMainWindow XAML 中定义的样式?

【问题讨论】:

  • 那么您希望能够让控件样式的消费者使用按钮吗?如果没有,并且已经修复,也可以在代码中设置。
  • 样式必须可以来自主样式表 XAML 字典。

标签: c# wpf xaml


【解决方案1】:

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

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

【讨论】:

  • 魅力十足!并且不需要暴露按钮。
  • @Harry 在 App.xaml 中的 Application.Resources 中定义默认按钮样式甚至可能就足够了。这样的样式会自动应用到应用程序中的所有按钮。
  • 无论如何,MyControl 样式中的封装更好,因为您直接只针对控件内的按钮。没有不必要的副作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多