views:

157

answers:

2

I have button Content that I want to use in multiple buttons on a UserControl in my Silverlight application. Here is the code for one button:

<Grid x:Name="LayoutRoot" Background="White">

    <Button Grid.Column="1" IsEnabled="{Binding PrivilegeChanged}" Height="24" Width="24">
        <Button.Content>
            <Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                x:Name="UndoIcon" Width="16" Height="16" Clip="F1 M 0,0L 16,0L 16,16L 0,16L 0,0" UseLayoutRounding="False">
                <Canvas x:Name="Arrow_2" Width="16" Height="16" Canvas.Left="0" Canvas.Top="0">
                    <Path Width="17.0154" Height="17" Canvas.Left="-0.5" Canvas.Top="-0.499999" Stretch="Fill" 
                        StrokeLineJoin="Round" Stroke="#FF006432" Fill="#FF00C800" 
                        Data="F1 M 12.5819,16C 14.1685,12.7951 14.1052,6.14911 11.0969,4.25C 9.23816,3.07665 6.71915,3.4789 5.40404,5.25L 8.12669,8.25L 0,8.91667L 0,9.53674e-007L 3.17642,3.25C 4.16648,1.91667 5.52584,0.61155 7.13664,0.25C 9.85332,-0.359774 13.4395,0.629333 15.0571,2.91667C 17.402,6.23256 15.0026,12.7401 12.5819,16"/>
                </Canvas>
            </Canvas>
        </Button.Content>
    </Button>

</Grid>

How can I make Button.Content reusable without removing the button outline?

A: 

Normally you would create a Template that creates the custom layout for your button. A quicker and more immediate solution for you would be to set the content within a Style, and apply the style to buttons you need.

Define the style with your content:

<Window.Resources>
    <Style x:Key="ButtonArrowStyle" TargetType="Button">
        <Setter Property="Content">
            <Setter.Value>
                <Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
            x:Name="UndoIcon" Width="16" Height="16" Clip="F1 M 0,0L 16,0L 16,16L 0,16L 0,0" UseLayoutRounding="False">
                    <Canvas x:Name="Arrow_2" Width="16" Height="16" Canvas.Left="0" Canvas.Top="0">
                        <Path Width="17.0154" Height="17" Canvas.Left="-0.5" Canvas.Top="-0.499999" Stretch="Fill" 
                    StrokeLineJoin="Round" Stroke="#FF006432" Fill="#FF00C800" 
                    Data="F1 M 12.5819,16C 14.1685,12.7951 14.1052,6.14911 11.0969,4.25C 9.23816,3.07665 6.71915,3.4789 5.40404,5.25L 8.12669,8.25L 0,8.91667L 0,9.53674e-007L 3.17642,3.25C 4.16648,1.91667 5.52584,0.61155 7.13664,0.25C 9.85332,-0.359774 13.4395,0.629333 15.0571,2.91667C 17.402,6.23256 15.0026,12.7401 12.5819,16"/>
                    </Canvas>
                </Canvas>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

And then define a button to use the style:

<Button Style="{StaticResource ButtonArrowStyle}"/>
Will Eddins
I have tried this, but I receive the error: "Value does not fall within the expected range." on Style="{StaticResource ButtonArrowStyle}".
Rachel Martin
@Rachel Martin: I used exactly what I have above in a test application and it worked fine. Are you sure there isn't another property that may be out of range? Try just copy-pasting exactly what's above (without fixing margins or changing values) and see if it can compile first.
Will Eddins
Well, I copied the Style exactly and placed it in Grid.Resources. I am currently using Silverlight 3 in Microsoft Visual Studio 2008 and Microsoft Expression Blend 3. With Visual Studio, I get the error message at runtime. With Blend, I get the error message at compilation, but it will still compile and give me an AG_E_INVALID_ARGUMENT error at runtime.
Rachel Martin
The reason this is not working is that a single Canvas cannot have more than one parent. You will not be able to set the Content in a Style in this manner.
KeithMahoney
@KeithMahoney: I don't believe the Canvas is the problem since I get an error when the Canvas only appears once on the page.
Rachel Martin
+2  A: 

The easiest approach would be to stick your button content design in its own UserControl :-

<UserControl x:Class="SilverlightApplication1.MyButton"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <Canvas Width="16" Height="16" Clip="F1 M 0,0L 16,0L 16,16L 0,16L 0,0" UseLayoutRounding="False">
        <Canvas Width="16" Height="16" Canvas.Left="0" Canvas.Top="0">
            <Path Width="17.0154" Height="17" Canvas.Left="-0.5" Canvas.Top="-0.499999" Stretch="Fill" 
                        StrokeLineJoin="Round" Stroke="#FF006432" Fill="#FF00C800" 
                        Data="F1 M 12.5819,16C 14.1685,12.7951 14.1052,6.14911 11.0969,4.25C 9.23816,3.07665 6.71915,3.4789 5.40404,5.25L 8.12669,8.25L 0,8.91667L 0,9.53674e-007L 3.17642,3.25C 4.16648,1.91667 5.52584,0.61155 7.13664,0.25C 9.85332,-0.359774 13.4395,0.629333 15.0571,2.91667C 17.402,6.23256 15.0026,12.7401 12.5819,16"/>
        </Canvas>
    </Canvas>
</UserControl>

Now you can create multiple instances of this user control where ever you need this content:-

<UserControl x:Class="SilverlightApplication1.Test"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="clr-namespace:SilverlightApplication1"
    Width="400" Height="300">
  <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel Orientation="Horizontal">
            <Button Grid.Column="1" IsEnabled="{Binding PrivilegeChanged}" Height="24" Width="24" Margin="2">
                <local:MyButton />
            </Button>
            <Button Grid.Column="1" IsEnabled="{Binding SomethingElseChanged}" Height="24" Width="24" Margin="2">
                <local:MyButton />
            </Button>
        </StackPanel>

    </Grid>
</UserControl>
AnthonyWJones