MrB3NiT0
MrB3NiT0

Reputation: 147

Change button appearance/icon

I want to change the icon on my button. Here is the xaml of my button:

<Button Name="InitPurgeBtn" Click="InitPurgeClick">
    <Rectangle Width="35" Height="45" Margin="0,0,0,0">
        <Rectangle.Fill>
            <VisualBrush Stretch="Fill" Visual="{StaticResource InitIcon}" />
        </Rectangle.Fill>
    </Rectangle>
</Button>

The probleme is I don't know how to acces the Visual property of the Rectangle of my button in my controller to change "InitIcon" by "PurgeIcon" All my icon are implement in xaml:

<Viewbox x:Key="ExtinctionIcon" Stretch="Uniform" x:Shared="False">
    <Canvas Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
        <Path Width="40" Height="40"  Stretch="Fill" Fill="{Binding Foreground, 
            RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" 
            Data="M15,24H17V22H15M16.56,{...}24H13V22H11M7,24H9V22H7V24Z"/>
    </Canvas>
</Viewbox>

Edit :

I change my button and he is like this now :

<Button Name="InitBtn" Style="{StaticResource RoundButton}" Width="70" Height="70" 
    Click="InitPurgeClick" Content="{StaticResource InitIcon}">                                  
</Button>

I want to change the icon in my code so I try to set Content property like this :

InitBtn.Content = "{StaticResource ExtinctionIcon}";

But this way just replace my icon with the string "StaticResource.."

Upvotes: 1

Views: 184

Answers (3)

Bradley Uffner
Bradley Uffner

Reputation: 16991

Updated to reflect new information

You updated your question with some new information that changes things a lot.

Since you are trying to update Button.Content in code, you won't be able to use the MarkupExtension. MarkupExtensions (the stuff inside { } in the XAML) are only evaluated when the view is initially created. After that, they behave just like regular strings, so trying to set one in code won't work.

To set the value in code, you will need to manually do what the MarkupExtension is doing; find the resource by name, and set the value directly. You can do this with the following code (assuming a reference to InitPurgeBtn).

InitPurgeBtn.Content = InitPurgeBtn.FindResource("ExtinctionIcon");

Previous Answer

You should be able to add your icon to the Content of the Button directly, as it seems to be defined as a resource somewhere (because of the x:Key attribute). Your code doesn't show where exactly that is though, so I can't grantee this will work without some modification.

<Button Name="InitPurgeBtn"
        Width="100" 
        Height="40" 
        Content="{StaticResource ExtinctionIcon}" />

In order for that to work the ExtinctionIcon resource will have to be defined someplace accessible to the button, meaning either in an ancestor of the button, or in App.xaml.

The fact that the resource is defined with x:Shared="false" seems to indicate that it was designed to be used in exactly this way, as that is required for visual elements that can possibly be hosted in multiple places simultaneously.


Alternatively, you could just copy and embed the icon directly in to the button.

<Button Name="InitPurgeBtn" 
        Click="InitPurgeClick">
    <Viewbox Stretch="Uniform">
        <Canvas Width="76" 
                Height="76" 
                Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
            <Path Width="40" 
                  Height="40"  
                  Stretch="Fill" 
                  Fill="{Binding Foreground, 
                                 RelativeSource={RelativeSource
                                                 Mode=FindAncestor, 
                                                 AncestorType=Button}}" 
                  Data="M15,24H17V22H15M16.56,{...}24H13V22H11M7,24H9V22H7V24Z"/>
        </Canvas>
    </Viewbox>
</Button>

Upvotes: 1

Peregrine
Peregrine

Reputation: 4546

If you just want a single (xaml) icon, you can bind the content property of your button to your icon resource.

The control below gives an enhanced display - a xaml icon plus a text caption, including two colours for the icon and support for disabled state.

MyXamlIconHost.cs

public enum CaptionPosition { None, ToLeftOfIcon, AboveIcon, ToRightOfIcon, BelowIcon }

public enum IconSize { Small, Medium, Large, XLarge, XxLarge }

public class myXamlIconHost : Control
{
    private static readonly Brush DefaultForeground = new SolidColorBrush(Color.FromRgb(32,32,32));
    private static readonly Brush DefaultHighlight = Brushes.DarkOrange;
    private static readonly Brush DefaultDisabledForeground = new SolidColorBrush(Color.FromRgb(192, 192, 192));
    private static readonly Brush DefaultDisabledHighlight = new SolidColorBrush(Color.FromRgb(128, 128, 128));

    static myXamlIconHost()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(myXamlIconHost), new FrameworkPropertyMetadata(typeof(myXamlIconHost)));
    }

    public FrameworkElement XamlIcon
    {
        get { return (FrameworkElement)GetValue(XamlIconProperty); }
        set { SetValue(XamlIconProperty, value); }
    }

    public static readonly DependencyProperty XamlIconProperty =
        DependencyProperty.Register("XamlIcon", typeof(FrameworkElement), typeof(myXamlIconHost), new PropertyMetadata(null));

    public IconSize IconSize
    {
        get { return (IconSize)GetValue(IconSizeProperty); }
        set { SetValue(IconSizeProperty, value); }
    }

    public static readonly DependencyProperty IconSizeProperty =
        DependencyProperty.Register("IconSize", typeof(IconSize), typeof(myXamlIconHost), new PropertyMetadata(IconSize.Medium));

    public string Caption
    {
        get { return (string)GetValue(CaptionProperty); }
        set { SetValue(CaptionProperty, value); }
    }

    public static readonly DependencyProperty CaptionProperty =
        DependencyProperty.Register("Caption", typeof(string), typeof(myXamlIconHost), new PropertyMetadata(null));

    public CaptionPosition CaptionPosition
    {
        get { return (CaptionPosition)GetValue(CaptionPositionProperty); }
        set { SetValue(CaptionPositionProperty, value); }
    }

    public static readonly DependencyProperty CaptionPositionProperty =
        DependencyProperty.Register("CaptionPosition", typeof(CaptionPosition), typeof(myXamlIconHost), new PropertyMetadata(CaptionPosition.ToRightOfIcon));

    public Brush StandardForeground
    {
        get { return (Brush)GetValue(StandardForegroundProperty); }
        set { SetValue(StandardForegroundProperty, value); }
    }

    public static readonly DependencyProperty StandardForegroundProperty =
        DependencyProperty.Register("StandardForeground", typeof(Brush), typeof(myXamlIconHost), new PropertyMetadata(DefaultForeground));

    public Brush StandardHighlight
    {
        get { return (Brush)GetValue(StandardHighlightProperty); }
        set { SetValue(StandardHighlightProperty, value); }
    }

    public static readonly DependencyProperty StandardHighlightProperty =
        DependencyProperty.Register("StandardHighlight", typeof(Brush), typeof(myXamlIconHost), new PropertyMetadata(DefaultHighlight));

    public Brush DisabledForeground
    {
        get { return (Brush)GetValue(DisabledForegroundProperty); }
        set { SetValue(DisabledForegroundProperty, value); }
    }

    public static readonly DependencyProperty DisabledForegroundProperty =
        DependencyProperty.Register("DisabledForeground", typeof(Brush), typeof(myXamlIconHost), new PropertyMetadata(DefaultDisabledForeground));

    public Brush DisabledHighlight
    {
        get { return (Brush)GetValue(DisabledHighlightProperty); }
        set { SetValue(DisabledHighlightProperty, value); }
    }

    public static readonly DependencyProperty DisabledHighlightProperty =
        DependencyProperty.Register("DisabledHighlight", typeof(Brush), typeof(myXamlIconHost), new PropertyMetadata(DefaultDisabledHighlight));
}

// ==============================================================================================================================================

public class myXamlIconSizeConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        const int defaultSize = 24;

        if (!(value is IconSize))
            return defaultSize;

        var iconSizeValue = (IconSize)value;

        switch (iconSizeValue)
        {
            case IconSize.Small:
                return defaultSize * 2 / 3;
            case IconSize.Large:
                return defaultSize * 3 / 2;
            case IconSize.XLarge:
                return defaultSize * 2;
            case IconSize.XxLarge:
                return defaultSize * 5 / 2;
            default:
                return defaultSize;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

MyXamlIconHost.xaml

<Style TargetType="{x:Type ctrl:myXamlIconHost}">
    <Setter Property="Focusable" Value="False" />
    <Setter Property="HorizontalAlignment" Value="Center" />
    <Setter Property="Padding" Value="0" />

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ctrl:myXamlIconHost}">
                <Grid Margin="{TemplateBinding Padding}">
                    <Grid.Resources>
                        <ctrl:myXamlIconSizeConverter x:Key="IconSizeConverter" />
                    </Grid.Resources>

                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>

                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>

                    <TextBlock x:Name="PART_CaptionTextBlock"
                               Grid.Row="1"
                               Grid.Column="0"
                               Margin="8,0,8,0"
                               HorizontalAlignment="Center"
                               VerticalAlignment="Center"
                               Foreground="{TemplateBinding StandardForeground}"
                               Text="{TemplateBinding Caption}" />

                    <!--  Set DataContext to "self" so that the Xaml Icon item can bind to the Foreground and BorderBrush properties  -->
                    <ContentControl x:Name="PART_IconPresenter"
                                    Grid.Row="1"
                                    Grid.Column="1"
                                    Width="{TemplateBinding IconSize,
                                                            Converter={StaticResource IconSizeConverter}}"
                                    Height="{TemplateBinding IconSize,
                                                             Converter={StaticResource IconSizeConverter}}"
                                    HorizontalAlignment="Center"
                                    VerticalAlignment="Center"
                                    BorderBrush="{TemplateBinding StandardHighlight}"
                                    Content="{TemplateBinding XamlIcon}"
                                    DataContext="{Binding RelativeSource={RelativeSource Self}}"
                                    Focusable="False"
                                    Foreground="{TemplateBinding StandardForeground}" />
                </Grid>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter TargetName="PART_CaptionTextBlock" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DisabledForeground}" />
                        <Setter TargetName="PART_IconPresenter" Property="BorderBrush" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DisabledHighlight}" />
                        <Setter TargetName="PART_IconPresenter" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DisabledForeground}" />
                    </Trigger>

                    <Trigger Property="CaptionPosition" Value="None">
                        <Setter TargetName="PART_CaptionTextBlock" Property="Visibility" Value="Collapsed" />
                    </Trigger>

                    <Trigger Property="CaptionPosition" Value="ToLeftOfIcon">
                        <Setter TargetName="PART_CaptionTextBlock" Property="Grid.Column" Value="0" />
                        <Setter TargetName="PART_CaptionTextBlock" Property="Grid.Row" Value="1" />
                        <Setter TargetName="PART_CaptionTextBlock" Property="Margin" Value="8,0,8,0" />
                    </Trigger>

                    <Trigger Property="CaptionPosition" Value="ToRightOfIcon">
                        <Setter TargetName="PART_CaptionTextBlock" Property="Grid.Column" Value="2" />
                        <Setter TargetName="PART_CaptionTextBlock" Property="Grid.Row" Value="1" />
                        <Setter TargetName="PART_CaptionTextBlock" Property="Margin" Value="8,0,8,0" />
                    </Trigger>

                    <Trigger Property="CaptionPosition" Value="AboveIcon">
                        <Setter TargetName="PART_CaptionTextBlock" Property="Grid.Column" Value="1" />
                        <Setter TargetName="PART_CaptionTextBlock" Property="Grid.Row" Value="0" />
                        <Setter TargetName="PART_CaptionTextBlock" Property="Margin" Value="8,0,8,4" />
                    </Trigger>

                    <Trigger Property="CaptionPosition" Value="BelowIcon">
                        <Setter TargetName="PART_CaptionTextBlock" Property="Grid.Column" Value="1" />
                        <Setter TargetName="PART_CaptionTextBlock" Property="Grid.Row" Value="2" />
                        <Setter TargetName="PART_CaptionTextBlock" Property="Margin" Value="8,4,8,0" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="VerticalAlignment" Value="Center" />
</Style>

Example Usage

<Window ... >
    <Window.Resources>
        <Grid x:Key="TestIcon" x:Shared="False" Background="Transparent">
            <Path Stretch="Fill" Data=" M 0,0 M 100,100 M 0,0 L 0,100 L 100,100 L 100,60 L 90,60 L 90,90 L 10,90 L 10,10 L 90,10 L 90,40 L 100,40 L 100,0 z" Fill="{ Binding Foreground, FallbackValue=Cyan}"/>
            <Path Stretch="Fill" Data=" M 0,0 M 100,100 M 70,45 L 100,45 L 100,55 L 70,55 z" Fill="{ Binding BorderBrush, FallbackValue=Magenta}"/>
        </Grid>
    </Window.Resources>

    <Button HorizontalAlignment="Center" VerticalAlignment="Center">
        <Border Background="LightBlue">
            <ctrls:myXamlIconHost Caption="The Caption" XamlIcon="{StaticResource TestIcon}" IconSize="XxLarge" Padding="20" />
        </Border>
    </Button>
</Window>

Upvotes: 0

Sham
Sham

Reputation: 930

You may use Content property.

 <Button Name="InitPurgeBtn" Width="100" Height="40">
        <Button.Content>
            <Image Source=".\Icon.PNG"/>
        </Button.Content>
    </Button>

Upvotes: 1

Related Questions