简体   繁体   中英

Setting the style on a xaml button programmatically fails

I'm working on a control. This control needs to be styled with input from an external source. I've looked for solutions and found a few that didn't break the code. However it is not styling the button. I set the style to the resources. Apply a reference to it on the button. Initialize the content, but the styles are not applied.

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

I've hardcoded the settings string. Normally this is dynamic and comes from an external resource. The question is why is dialogButton.Style = this.Resources["key"] as Style; not applying the desired style effects?

The image shows the result now (left) and the desired effect (right). No rounded border and a different border-color. And no, red isn't going to be the final color. It's for debugging.

在此处输入图片说明

There are two issues in your code.

First, you are using Border.BorderBrushProperty and Border.BorderThicknessProperty which are not the dependency properties in Button control. You should change them to Button.BorderBrushProperty and Button.BorderThicknessProperty respectively, like the following -

styleOverride.Setters.Add(new Setter(Button.BorderBrushProperty, colorConverter(settings[2])));
styleOverride.Setters.Add(new Setter(Button.BorderThicknessProperty, new Thickness(double.Parse(settings[1]))));

The second issue is that there's no CornerRadius dependency property in a Button control. So you can't simply change it to Button.CornerRadiusProperty .

The workaround is, define a local Button Style inside your page, and then use TemplateBinding to bind the CornerRadius of the Border (inside the ControlTemplate of the Button ) to the Tag dependency property. This part is easier to be done in xaml.

CornerRadius="{TemplateBinding Tag}"

And then, you just need to apply the Style as the BaseOn of your override Style and update the Tag property instead.

var styleOverride = new Style(typeof(Button))
{
    BasedOn = (Style)this.Resources["ButtonStyle1"]
};

styleOverride.Setters.Add(new Setter(Button.TagProperty, new CornerRadius(0)));

Here attaches the full xaml Button 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>

I tested the code and the result is exactly what you expected.

Hope this helps!

Do not set Style in code behind directly:

dialogButton.Style = this.Resources["key"] as Style;

but with SetValue method:

var style = this.Resources["key"] as Style; // or this.TryFindResource("key") as Style;
dialogButton.SetValue(StyleProperty, style);

It seems like style is applyed, but red border overlays png. Try to comment out line:

/* styleOverride.Setters.Add(new Setter(Border.BorderBrushProperty, colorConverter(settings[2]))); */

Now background image become visible. Maybe solution is to resize image to 40x40 pixels with margins?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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