Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a bindable Point in C# WPF

I know multiple inheritence is out, but is there a way to create a wrapper for System.Windows.Point that can inherit from it but still implement bindable dependency properties?

I'm trying to code so that for my XAML I can create staments like the following without issue:

<custom:Point X="{Binding Width, ElementName=ParentControlName}" Y="{Binding Height, ElementName=ParentControlName}" />

It would make coding things like Polygons, Paths, LineSegments and other controls so much easier.

The following code is provided as wishful thinking and I understand that it will in no way work, but this is the kind of thing I want to be able to do:

public class BindablePoint: DependencyObject, Point
{
    public static readonly DependencyProperty XProperty =
    DependencyProperty.Register("X", typeof(double), typeof(BindablePoint),
    new FrameworkPropertyMetadata(default(double), (sender, e) =>
    {
        BindablePoint point = sender as BindablePoint;
        point.X = (double) e.NewValue;
    }));

    public static readonly DependencyProperty YProperty =
    DependencyProperty.Register("Y", typeof(double), typeof(BindablePoint),
    new FrameworkPropertyMetadata(default(double), (sender, e) =>
    {
        BindablePoint point = sender as BindablePoint;
        point.Y = (double)e.NewValue;
    }));

    public new double X
    {
        get { return (double)GetValue(XProperty); }
        set 
        { 
            SetValue(XProperty, value);
            base.X = value;
        }
    }

    public new double Y
    {
        get { return (double)GetValue(YProperty); }
        set
        {
            SetValue(YProperty, value);
            base.Y = value;
        }
    }
}

like image 762
Ross Graeber Avatar asked Feb 24 '11 17:02

Ross Graeber


1 Answers

Unfortunately, Point is a struct, and structs don't support inheritance. From MSDN

Note Structs do not support inheritance, but they can implement interfaces. For more information, see Interfaces (C# Programming Guide).

Maybe this doesn't answer your question directly but you can easily bind a Point with the help of a Converter. In your case it would be like

<SomeControl.SomePointProperty>
    <MultiBinding Converter="{StaticResource PointConverter}">
        <Binding ElementName="ParentControlName"
                 Path="Width"/>
        <Binding ElementName="ParentControlName"
                 Path="Height"/>
    </MultiBinding>                                        
</SomeControl.SomePointProperty>

PointConverter

public class PointConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double xValue = (double)values[0];
        double yValue = (double)values[1];
        return new Point(xValue, yValue);
    }
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

If you just want to bind the X value and have a static Y value you could do this like

<SomeControl SomePointProperty="{Binding Path=Width,
                                         ElementName=ParentControlName,
                                         Converter={StaticResource PointXConverter},
                                         ConverterParameter=20}"/>

PointXConverter

public class PointXConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double progressBarValue = (double)value;
        double yValue = System.Convert.ToDouble(parameter);
        return new Point(progressBarValue, yValue);
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
} 
like image 99
Fredrik Hedblad Avatar answered Oct 23 '22 15:10

Fredrik Hedblad