How to use WPF custom control properties in XAML Template?

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); }
        }
    }

Answers


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.


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.


Need Your Help

html5 pattern that will not allow only numbers but accepts everything

javascript html regex html5

I have an input text field in my form but i don't know how to filter the input that can all letters and special characters but will not accept numbers.

Bind to bound item?

c# wpf binding windows-8.1

I have Comments class, to which I am binding: