tags:

views:

44

answers:

2

Hey all,

I've created a custom control that is intended to be used as a button but has properties to specify points for a polygon (to be drawn inside the button) and two colors for the gradient. I've declared all the properties in the code and then written the template in the XAML but it doesn't seem to be working. If I hard-code the values into the XAML it works just fine but nothing seems to be happening if I use the property values through TemplateBinding. Any ideas on how to get this to work?

Here's my XAML:

<Window x:Class="WPFTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:WPFTest">
    <StackPanel>
        <StackPanel.Resources>
            <Style TargetType="my:GradientButton">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type my:GradientButton}">
                            <Grid>
                                <Ellipse Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" Stroke="{TemplateBinding Foreground}" VerticalAlignment="Top" HorizontalAlignment="Left">
                                    <Ellipse.Fill>
                                        <LinearGradientBrush>
                                            <GradientStop Color="{TemplateBinding GradientStart}" Offset="0"></GradientStop>
                                            <GradientStop Color="{TemplateBinding GradientEnd}" Offset="1"></GradientStop>
                                        </LinearGradientBrush>
                                    </Ellipse.Fill>
                                </Ellipse>
                                <Polygon Points="{TemplateBinding PlayPoints}" Fill="{TemplateBinding Foreground}" />
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </StackPanel.Resources>
        <my:GradientButton Content="Button" Height="50" x:Name="gradientButton1" Width="50" GradientStart="#CCCCCC" GradientEnd="#777777" />
    </StackPanel>
</Window>

And here's the code for the custom control:

public class GradientButton : Button
    {
        internal static DependencyProperty GradientStartProperty;
        internal static DependencyProperty GradientEndProperty;
        internal static DependencyProperty PlayPointsProperty;

        static GradientButton()
        {
            GradientStartProperty = DependencyProperty.Register("GradientStart", typeof(Color), typeof(GradientButton));
            GradientEndProperty = DependencyProperty.Register("GradientEnd", typeof(Color), typeof(GradientButton));
            PlayPointsProperty = DependencyProperty.Register("PlayPoints", typeof(Point[]), typeof(GradientButton));
        }

        public Color GradientStart
        {
            get { return (Color)base.GetValue(GradientStartProperty); }
            set { SetValue(GradientStartProperty, value); }
        }

        public Color GradientEnd
        {
            get { return (Color)base.GetValue(GradientEndProperty); }
            set { SetValue(GradientEndProperty, value); }
        }

        public Point[] PlayPoints
        {
            get //hardcoded return at the moment to get it to work, but this will change later
            {
                System.Collections.Generic.List<Point> result = new System.Collections.Generic.List<Point>();

                double left = this.Width / 2.77;
                double top = this.Height / 4.17;
                double right = this.Width / 1.43;
                double middle = this.Height / 2.0;
                double bottom = this.Height / 1.32;

                result.Add(new Point(left, top));
                result.Add(new Point(right, middle));
                result.Add(new Point(left, bottom));

                return result.ToArray();
            }
            set { SetValue(PlayPointsProperty, value); }
        }
    }
+1  A: 

Polygon.Points is of type PointCollection. I don't believe a Point[] fits that type. You will need to either change the type of PlayPoints or use a IValueConverter to make the change it's type.

Stephan
Thanks. That sorted the issue for the polygon. It is now drawing correctly. My colors are still a problem though...
Sonny Boy
A: 

Try using this instead for your Color bindings:

Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=GradientStart}"

TemplateBinding only works in limited situations where declarations are in elements of the visual tree of a ControlTemplate, which is not the case for your LinearGradientBrush. You can see the same behavior, and use the same fix, inside Trigger Setters in a ControlTemplate.

John Bowen
Sorry, John. I tried those changes to no avail. No exceptions, but no change in gradient on my Ellipse.
Sonny Boy
What is it that you're seeing for your Ellipse? Are you getting errors in your Output window?
John Bowen
@John - No errors, and the ellipse's background is just plain white. No colors and no gradient. It looks exactly the same as if I was applying no background at all.
Sonny Boy