Frage

I'm writing my first XAML template (be nice, please) for a custom button, and I'm trying to make a common occurrence (button icons) more integral to the setup.

Currently my template is as follows:

<ControlTemplate TargetType="Button" x:Key="tButton">
    <Grid>
        <Border x:Name="Background" CornerRadius="2" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
            <Grid Background="{TemplateBinding Background}">
                <Rectangle x:Name="BackgroundGradient" >
                </Rectangle>
            </Grid>
        </Border>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="auto" />
            </Grid.ColumnDefinitions>

            <!-- icon image -->
            <Image Grid.Column="0" />

            <ContentPresenter
                            Grid.Column="1"
                            x:Name="contentPresenter"
                            Content="{TemplateBinding Content}"
                            ContentTemplate="{TemplateBinding ContentTemplate}"
                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                            Margin="{TemplateBinding Padding}" />
        </Grid>
        <Rectangle x:Name="DisabledVisualElement" RadiusX="3" RadiusY="3" Fill="#FFFFFFFF" Opacity="0" IsHitTestVisible="false" />
        <Rectangle x:Name="FocusVisualElement"    RadiusX="2" RadiusY="2" Margin="1" Stroke="#FF6DBDD1" StrokeThickness="1" Opacity="0" IsHitTestVisible="false" />
    </Grid>
</ControlTemplate>

So I'm all set up to have text and an image, and the text part even works, but what I'd really love (and have no idea how to do) is pass the icon into the button.

I was trying to figure out how to get a custom property (for a URI) on the button that could be set in styling, but it all sort of went right over my head (it was a lot to hold in there, when combined with learning this whole templating thing). Is that even a valid approach? Maybe some way I could have the template pick up any image it finds in the button contents and use it as indicated?

Essentially, is it possible to have a standardized way for all of my buttons to have an option to have an icon? It would be much nicer than the messy solution of having every button have an image and a textblock, each of which need their own context-sensitive styling.

Finally, I (unfortunately) only have access to the XAML. I can do just about anything I want with it, but this is a redesign of an existing panel, and I don't have access to the C# functional bits.

War es hilfreich?

Lösung

Implement a button with a property for the icon source

public class IconButton : Button
{
    public static readonly DependencyProperty IconSourceProperty =
        DependencyProperty.Register("IconSource", typeof(string), typeof(IconButton), new PropertyMetadata(default(string)));

    public string IconSource
    {
        get { return (string)GetValue(IconSourceProperty); }
        set { SetValue(IconSourceProperty, value); }
    }
}

Adjust your template to fit that button and bind the image source to your custom property

<ControlTemplate TargetType="{x:Type local:IconButton}" x:Key="tbutton">
<Grid>
    <Border x:Name="Background" CornerRadius="2" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
        <Grid Background="{TemplateBinding Background}">
            <Rectangle x:Name="BackgroundGradient" >
            </Rectangle>
        </Grid>
    </Border>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto" />
        </Grid.ColumnDefinitions>

        <!-- icon image -->
        <Image Grid.Column="0" Source="{TemplateBinding IconSource}"/>

        <ContentPresenter
                        Grid.Column="1"
                        x:Name="contentPresenter"
                        Content="{TemplateBinding Content}"
                        ContentTemplate="{TemplateBinding ContentTemplate}"
                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                        Margin="{TemplateBinding Padding}" />
    </Grid>
    <Rectangle x:Name="DisabledVisualElement" RadiusX="3" RadiusY="3" Fill="#FFFFFFFF" Opacity="0" IsHitTestVisible="false" />
    <Rectangle x:Name="FocusVisualElement"    RadiusX="2" RadiusY="2" Margin="1" Stroke="#FF6DBDD1" StrokeThickness="1" Opacity="0" IsHitTestVisible="false" />
</Grid>

And simple use it

<local:IconButton IconSource="Resources\1.jpg" Template="{StaticResource tbutton}"></local:IconButton>

Andere Tipps

In addion to Omribitan :

CS:

  public class IconButton : Button
  {
       public static readonly DependencyProperty ImageSourceProperty =
        DependencyProperty.Register("ImageSource", typeof(string), typeof(IconButton), new PropertyMetadata(null));

        public string ImageSource
        {
            get { return (string)GetValue(ImageSourceProperty); }
            set { SetValue(ImageSourceProperty, value); }
        }
   }

xaml :

 <ControlTemplate TargetType="Button" x:Key="tButton">    
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition  />
        </Grid.ColumnDefinitions>

        <!-- icon image -->
        <Image x:Name=img ImageSource="{TemplateBinding ImageSource}" />

        <ContentPresenter Grid.Column="1" /> 
   </Grid>

   <ControlTemplate.Triggers>
        <Trigger Property="ImageSource" Value="{x:Null}">
            <Setter TargetName=img Property=Visibility Value=Collapesd/>
        </Trigger>
   </ControlTemplate.Triggers>  
</ControlTemplate>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top