1

Is it possible to use a PlaceHolder in a WPF Style that could later be assigned a value by the implementing control? Something like:

<Style x:Key="BigButton" TargetType="{x:Type Button}">
    <Setter Property="Foreground" Value="#58290a" />
    <Setter Property="FontFamily" Value="Lucida Console" />
    <Setter Property="FontSize" Value="24" />
    <Setter Property="Content">
        <Setter.Value>
            <StackPanel>
                <Image Source=[SOME PLACEHOLDER]></Image>
                <TextBlock>[ANOTHER PLACEHOLDER]</TextBlock>
            </StackPanel>
        </Setter.Value>
    </Setter>
</Style>

and then a Button could assign an image path to this place-holder like this:

<Button Name="btn" Style="{StaticResource BigButton}">
    <SOME CLEVER WAY OF ASSIGNING A PATH TO Style.Content.StackPanel.Image.Source and Style.Content.StackPanel.TextBlock.Text>
</Button>

2 Answers 2

1

This sounds like a job for Attached properties.

Create a utility class with you "placeholder properties":

public static class BigButtonUtils
{
    public static Uri GetBBImage(DependencyObject obj)
    {
        return (Uri)obj.GetValue(BBImageProperty);
    }
    public static void SetBBImage(DependencyObject obj, Uri value)
    {
        obj.SetValue(BBImageProperty, value);
    }
    // Using a DependencyProperty as the backing store for BBImage.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty BBImageProperty =
        DependencyProperty.RegisterAttached("BBImage", typeof(Uri), typeof(BigButtonUtils), new UIPropertyMetadata(null));


    public static string GetBBCaption(DependencyObject obj)
    {
        return (string)obj.GetValue(BBCaptionProperty);
    }
    public static void SetBBCaption(DependencyObject obj, string value)
    {
        obj.SetValue(BBCaptionProperty, value);
    }
    // Using a DependencyProperty as the backing store for BBCaption.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty BBCaptionProperty =
        DependencyProperty.RegisterAttached("BBCaption", typeof(string), typeof(BigButtonUtils), new UIPropertyMetadata(null));
}

Apply those properties on a Button..

<Button Style="{StaticResource BigButtonStyle}"
        bb:BigButtonUtils.BBImage="http://programming.enthuses.me/1.png" 
        bb:BigButtonUtils.BBCaption="My caption" />

..and use the property values in your Style:

<Style x:Key="BigButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Foreground" Value="#58290a" />
    <Setter Property="FontFamily" Value="Lucida Console" />
    <Setter Property="FontSize" Value="24" />
    <Setter Property="Content">
        <Setter.Value>
            <StackPanel DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Button}}">
                <Image Source="{Binding Path=(bb:BigButtonUtils.BBImage)}" Stretch="None" />
                <TextBlock Text="{Binding Path=(bb:BigButtonUtils.BBCaption)}" />
            </StackPanel>
        </Setter.Value>
    </Setter>
</Style>

NOTE: Don't set any other content on the Button, like <Button Content="..." /> or <Button ...>SomeContent</Button>, as that would override the "placeholder content" from the Style.

Sign up to request clarification or add additional context in comments.

2 Comments

I like that, though I'd prefer to have a XAML-only solution (without the code-behind). Can we build one? Also, being relatively new to WPF, may I ask, do you see any difference between what you're suggesting and what Florian has posted below? Any particular advantage/disadvantage between the two?
The difference is that the attached properties (BBImage and BBCaption) don't belong in the code-behind of your Window or UserControl. You can put the BigButtonUtils class (along with BigButtonStyle) in a separate project/assembly and use it everywhere. I don't think you'll be able to do what you're looking for without writing any code, but at least this way you only have to write it once, and then apply it to as many buttons as you want.
0

You can use properties as placeholder:

    <Style x:Key="BigButton" TargetType="{x:Type Button}">
        <Setter Property="Foreground" Value="#58290a" />
        <Setter Property="FontFamily" Value="Lucida Console" />
        <Setter Property="FontSize" Value="24" />
        <Setter Property="Content">
            <Setter.Value>
                <StackPanel>
                    <TextBlock Text="{Binding Path=Placeholder}"></TextBlock>
                </StackPanel>
            </Setter.Value>
        </Setter>
    </Style>

The property:

    public string _placeholder;
    public string Placeholder
    {
        get
        {
            return _placeholder;
        }
        set
        {
            _placeholder = value;
            OnPropertyChanged("Placeholder");
        }
    }

Now you can modify this property when you want, e.g. through a OnClick-EventHandler or a Command.

1 Comment

Is there a XAML way of doing it (without using the code-behind)? What if I have this style in a ResourceDictionary and want to apply it to 3 Buttons in my Window simply by <Button Style="{StaticResource BigButton}">[XAML code to assign a value to the Style PlaceHolder]</Button>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.