【问题标题】:WPF Control Template programmatically with C# code使用 C# 代码以编程方式的 WPF 控件模板
【发布时间】:2015-12-09 10:25:14
【问题描述】:

我正在尝试为按钮创建样式,尤其是更改 IsMouseOver 样式(必须通过控件模板覆盖它)。我正在尝试这段代码(我必须使用 c#,没有 xaml),但按钮只变成黄色,IsMouseOver 没有做任何事情。

private void CreateElement(int i)
{
    UIElementOut[i] = new Button();
    var uiElement = (Button)UIElementOut[i];
    uiElement.Width = 100;
    uiElement.Height = 100;
    uiElement.VerticalAlignment = VerticalAlignment.Center;
    uiElement.HorizontalAlignment = HorizontalAlignment.Center;
    uiElement.Content = TextIn[i];
    uiElement.FontFamily = new FontFamily(FFontInput[i]);
    uiElement.FontSize = Convert.ToDouble(FontSizeIn[i]);

    Style MyButtonStyle = new Style();
    ControlTemplate templateButton = new ControlTemplate(typeof(Button));
    FrameworkElementFactory elemFactory = new FrameworkElementFactory(typeof(Button));
    elemFactory.Name = "myButton";
    elemFactory.SetValue(Button.BackgroundProperty, Brushes.Yellow);
    templateButton.VisualTree = elemFactory;
    elemFactory.AppendChild(new FrameworkElementFactory(typeof(ContentPresenter)));

    Trigger templateTrigger = new Trigger { Property = Button.IsPressedProperty, Value = true };
    templateTrigger.Setters.Add(new Setter { Property = Button.ForegroundProperty, Value = Brushes.Violet });
    templateTrigger.Setters.Add(new Setter { Property = Button.BackgroundProperty, Value = Brushes.Red });
    templateButton.Triggers.Add(templateTrigger);

    Setter setter = new Setter { TargetName = "myButton", Property = Button.TemplateProperty, Value = templateButton };
    MyButtonStyle.Setters.Add(setter);
    uiElement.Style = MyButtonStyle;
    uiElement.Template = templateButton;
}

【问题讨论】:

  • 当你说“我必须使用 c#,没有 xaml”时,你真的是指“我必须”吗?还是说“我想”更准确?因为数据绑定是执行此操作的正确方法,我想不出任何人会“必须”按照您的方式进行操作的单一原因。如果您阐明了您认为需要以错误方式执行此操作的原因,则很有可能有一个很好的解决方案可以完全避免它。
  • @lecloneur 为什么将Button 放在按钮模板中?外部Button 与内部Button 不同,它们也不会以任何方式链接。我也没有看到IsMouseOver 的行为。只有IsPressed 触发器。
  • Mark Feldman,我必须使用 c#,因为我正在为一个名为 vvvv 的软件编写 WPF 控制插件,我完全不知道如何将 xaml 与 vvvv 一起使用。这就是我只在这里使用 c# 的原因,而且我知道这绝对不是最简单的方法……@dkozl,在发布我做错的代码时,你确实应该看到 IsMouseOver 而不是 IsPressed。关于内部和外部按钮我不知道,所以我会搜索一下(我是初学者)。谢谢

标签: c# wpf templates controls


【解决方案1】:

您似乎将Button 放在按钮的模板中。这个内部按钮与外部按钮不同,它们也不会以任何方式链接。通常我会期望例如Border 在那个Background 属性绑定到模板化父级的地方。它的默认值将被设置为 Style 的 setter 并由 Style 的触发器更改

Style MyButtonStyle = new Style();
ControlTemplate templateButton = new ControlTemplate(typeof(Button));
FrameworkElementFactory elemFactory = new FrameworkElementFactory(typeof(Border));
elemFactory.SetBinding(Border.BackgroundProperty, new Binding { RelativeSource = RelativeSource.TemplatedParent, Path = new PropertyPath("Background") });
templateButton.VisualTree = elemFactory;
elemFactory.AppendChild(new FrameworkElementFactory(typeof(ContentPresenter)));
MyButtonStyle.Setters.Add(new Setter { Property = Button.BackgroundProperty, Value = Brushes.Yellow });
MyButtonStyle.Setters.Add(new Setter { Property = Button.TemplateProperty, Value = templateButton });
Trigger styleTrigger = new Trigger { Property = Button.IsMouseOverProperty, Value = true };
styleTrigger.Setters.Add(new Setter { Property = Button.ForegroundProperty, Value = Brushes.Violet });
styleTrigger.Setters.Add(new Setter { Property = Button.BackgroundProperty, Value = Brushes.Red });
MyButtonStyle.Triggers.Add(styleTrigger);

相当于 XAML 中的相同代码

<Style TargetType="{x:Type Button}">
    <Setter Property="Background" Value="Yellow"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}">
                    <ContentPresenter/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" Value="Red"/>
            <Setter Property="Foreground" Value="Violet"/>
        </Trigger>
    </Style.Triggers>
</Style>

但是,由于您更改了Template,这有效地使按钮的外观和感觉,您需要注意您的Button 不会有默认Button 的行为,直到您手动添加它.

【讨论】:

  • 非常感谢,它正在工作。起初没有得到边框的东西,当我试图“样式化”按钮而不是“边框”时并不那么明显......
  • 我现在不明白的是为什么按钮的内容不再居中并受 ContentAlignmentProperty 影响?
  • 就像我说的那样,这是因为您更改了 Button 的模板,因此您完全重新设计了它的外观和行为方式。在您添加之前,它不会有任何功能。在这种情况下,您需要将ContentPresenter.HorizontalAlignment 绑定(与Border.Background 相同)到Button.HorizontalContentAlignment 并类似地用于垂直对齐
猜你喜欢
  • 2011-10-19
  • 2011-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多