以编程方式在 xaml 按钮上设置样式失败
Setting the style on a xaml button programmatically fails
我正在开发一个控件。此控件需要使用来自外部源的输入来设置样式。我一直在寻找解决方案并找到了一些没有破坏代码的解决方案。但是它没有为按钮设置样式。我将样式设置为资源。在按钮上应用对它的引用。初始化内容,但不应用样式。
public MainPage()
{
//String[] settings = Application.Current.Resources["settings"].ToString().Split(new Char[1] { '\u003A' });
String[] settings = "_icons/pngp/2933.png:1:ff0000:Select files from disk...:36:36".Split(new Char[1] { '\u003A' });
//style the dialog button
ImageBrush image = new ImageBrush();
image.ImageSource = new BitmapImage(new Uri(settings[0], UriKind.Relative));
Button dialogButton = new Button();
dialogButton.Background = image;
var styleOverride = new Style(typeof(Button)) ;
styleOverride.Setters.Add(new Setter(Border.CornerRadiusProperty, new CornerRadius(0)));
styleOverride.Setters.Add(new Setter(Border.BorderBrushProperty, colorConverter(settings[2])));
styleOverride.Setters.Add(new Setter(Border.BorderThicknessProperty, new Thickness(double.Parse(settings[1]))));
this.Resources.Add("key", styleOverride);
dialogButton.Style = this.Resources["key"] as Style;
dialogButton.Height = double.Parse(settings[4]);
dialogButton.Width = double.Parse(settings[5]);
//attach the click handler;
dialogButton.Click += dialogButton_Click;
ToolTip tooltip = new ToolTip();
tooltip.Content = settings[3];
ToolTipService.SetToolTip(dialogButton, tooltip);
this.InitializeComponent();
this.LayoutRoot.Children.Add(dialogButton);
this.LayoutRoot.Drop += this.Canvas_Drop;
}
我已经对 settings
字符串进行了硬编码。通常这是动态的并且来自外部资源。问题是为什么 dialogButton.Style = this.Resources["key"] as Style;
没有应用所需的样式效果?
图像显示了现在的结果(左)和期望的效果(右)。没有圆角边框和不同的 border-color。不,红色不会是最终的颜色。用于调试。
不要直接在代码后面设置Style:
dialogButton.Style = this.Resources["key"] as Style;
但使用 SetValue
方法:
var style = this.Resources["key"] as Style; // or this.TryFindResource("key") as Style;
dialogButton.SetValue(StyleProperty, style);
似乎应用了样式,但红色边框覆盖了 png。
尝试注释掉行:
/* styleOverride.Setters.Add(new Setter(Border.BorderBrushProperty, colorConverter(settings[2]))); */
现在可以看到背景图片了。
也许解决方案是将图像调整为 40x40 像素并留有边距?
您的代码中有两个问题。
首先,您使用的 Border.BorderBrushProperty
和 Border.BorderThicknessProperty
不是 Button
控件中的依赖属性。您应该将它们分别更改为 Button.BorderBrushProperty
和 Button.BorderThicknessProperty
,如下所示 -
styleOverride.Setters.Add(new Setter(Button.BorderBrushProperty, colorConverter(settings[2])));
styleOverride.Setters.Add(new Setter(Button.BorderThicknessProperty, new Thickness(double.Parse(settings[1]))));
第二个问题是 Button
控件中没有 CornerRadius
依赖项 属性。所以你不能简单地把它改成 Button.CornerRadiusProperty
.
解决方法是,在你的页面中定义一个本地Button
Style
,然后使用TemplateBinding
绑定Border
的CornerRadius
(在 Button
的 ControlTemplate
内)到 Tag
依赖项 属性。这部分在 xaml.
中更容易完成
CornerRadius="{TemplateBinding Tag}"
然后,您只需应用 Style
作为覆盖 Style
的 BaseOn
并更新 Tag
属性。
var styleOverride = new Style(typeof(Button))
{
BasedOn = (Style)this.Resources["ButtonStyle1"]
};
styleOverride.Setters.Add(new Setter(Button.TagProperty, new CornerRadius(0)));
这里附上完整的xamlButton
Style
.
<Style x:Key="ButtonStyle1" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundAnimation"/>
<ColorAnimation Duration="0" To="#F2FFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#CCFFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#7FFFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0" To="#FF6DBDD1" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="Background"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundAnimation"/>
<ColorAnimation Duration="0" To="#D8FFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#C6FFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#8CFFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#3FFFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Background" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="White" CornerRadius="{TemplateBinding Tag}">
<Grid Background="{TemplateBinding Background}" Margin="1" d:IsHidden="True">
<Border x:Name="BackgroundAnimation" Background="#FF448DCA" Opacity="0" d:IsHidden="True"/>
<Rectangle x:Name="BackgroundGradient" d:IsHidden="True">
<Rectangle.Fill>
<LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
<GradientStop Color="#FFFFFFFF" Offset="0"/>
<GradientStop Color="#F9FFFFFF" Offset="0.375"/>
<GradientStop Color="#E5FFFFFF" Offset="0.625"/>
<GradientStop Color="#C6FFFFFF" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Border>
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" d:IsHidden="True"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我测试了代码,结果正是你所期望的。
希望对您有所帮助!
我正在开发一个控件。此控件需要使用来自外部源的输入来设置样式。我一直在寻找解决方案并找到了一些没有破坏代码的解决方案。但是它没有为按钮设置样式。我将样式设置为资源。在按钮上应用对它的引用。初始化内容,但不应用样式。
public MainPage()
{
//String[] settings = Application.Current.Resources["settings"].ToString().Split(new Char[1] { '\u003A' });
String[] settings = "_icons/pngp/2933.png:1:ff0000:Select files from disk...:36:36".Split(new Char[1] { '\u003A' });
//style the dialog button
ImageBrush image = new ImageBrush();
image.ImageSource = new BitmapImage(new Uri(settings[0], UriKind.Relative));
Button dialogButton = new Button();
dialogButton.Background = image;
var styleOverride = new Style(typeof(Button)) ;
styleOverride.Setters.Add(new Setter(Border.CornerRadiusProperty, new CornerRadius(0)));
styleOverride.Setters.Add(new Setter(Border.BorderBrushProperty, colorConverter(settings[2])));
styleOverride.Setters.Add(new Setter(Border.BorderThicknessProperty, new Thickness(double.Parse(settings[1]))));
this.Resources.Add("key", styleOverride);
dialogButton.Style = this.Resources["key"] as Style;
dialogButton.Height = double.Parse(settings[4]);
dialogButton.Width = double.Parse(settings[5]);
//attach the click handler;
dialogButton.Click += dialogButton_Click;
ToolTip tooltip = new ToolTip();
tooltip.Content = settings[3];
ToolTipService.SetToolTip(dialogButton, tooltip);
this.InitializeComponent();
this.LayoutRoot.Children.Add(dialogButton);
this.LayoutRoot.Drop += this.Canvas_Drop;
}
我已经对 settings
字符串进行了硬编码。通常这是动态的并且来自外部资源。问题是为什么 dialogButton.Style = this.Resources["key"] as Style;
没有应用所需的样式效果?
图像显示了现在的结果(左)和期望的效果(右)。没有圆角边框和不同的 border-color。不,红色不会是最终的颜色。用于调试。
不要直接在代码后面设置Style:
dialogButton.Style = this.Resources["key"] as Style;
但使用 SetValue
方法:
var style = this.Resources["key"] as Style; // or this.TryFindResource("key") as Style;
dialogButton.SetValue(StyleProperty, style);
似乎应用了样式,但红色边框覆盖了 png。 尝试注释掉行:
/* styleOverride.Setters.Add(new Setter(Border.BorderBrushProperty, colorConverter(settings[2]))); */
现在可以看到背景图片了。 也许解决方案是将图像调整为 40x40 像素并留有边距?
您的代码中有两个问题。
首先,您使用的 Border.BorderBrushProperty
和 Border.BorderThicknessProperty
不是 Button
控件中的依赖属性。您应该将它们分别更改为 Button.BorderBrushProperty
和 Button.BorderThicknessProperty
,如下所示 -
styleOverride.Setters.Add(new Setter(Button.BorderBrushProperty, colorConverter(settings[2])));
styleOverride.Setters.Add(new Setter(Button.BorderThicknessProperty, new Thickness(double.Parse(settings[1]))));
第二个问题是 Button
控件中没有 CornerRadius
依赖项 属性。所以你不能简单地把它改成 Button.CornerRadiusProperty
.
解决方法是,在你的页面中定义一个本地Button
Style
,然后使用TemplateBinding
绑定Border
的CornerRadius
(在 Button
的 ControlTemplate
内)到 Tag
依赖项 属性。这部分在 xaml.
CornerRadius="{TemplateBinding Tag}"
然后,您只需应用 Style
作为覆盖 Style
的 BaseOn
并更新 Tag
属性。
var styleOverride = new Style(typeof(Button))
{
BasedOn = (Style)this.Resources["ButtonStyle1"]
};
styleOverride.Setters.Add(new Setter(Button.TagProperty, new CornerRadius(0)));
这里附上完整的xamlButton
Style
.
<Style x:Key="ButtonStyle1" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundAnimation"/>
<ColorAnimation Duration="0" To="#F2FFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#CCFFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#7FFFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0" To="#FF6DBDD1" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="Background"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundAnimation"/>
<ColorAnimation Duration="0" To="#D8FFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#C6FFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#8CFFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#3FFFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Background" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="White" CornerRadius="{TemplateBinding Tag}">
<Grid Background="{TemplateBinding Background}" Margin="1" d:IsHidden="True">
<Border x:Name="BackgroundAnimation" Background="#FF448DCA" Opacity="0" d:IsHidden="True"/>
<Rectangle x:Name="BackgroundGradient" d:IsHidden="True">
<Rectangle.Fill>
<LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
<GradientStop Color="#FFFFFFFF" Offset="0"/>
<GradientStop Color="#F9FFFFFF" Offset="0.375"/>
<GradientStop Color="#E5FFFFFF" Offset="0.625"/>
<GradientStop Color="#C6FFFFFF" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Border>
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" d:IsHidden="True"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我测试了代码,结果正是你所期望的。
希望对您有所帮助!