Yellow
Yellow

Reputation: 3966

Creating a generic DependencyProperty

I have a generic class that takes a template T which should be a non-nullable object:

class Point<T> where T : struct
{
    public T x;
    public T y;
}

For reasons that I won't go into here, I really need T to be a struct, not any object or class.

I want to make a UserControl that has an instance of this class as DependencyProperty, for example:

public class MyUserControl : UserControl
{
     static MyUserControl () {}


    public static readonly DependencyProperty PointDependencyProperty = 
        DependencyProperty.Register(
          "MyPoint",
          typeof(Point<???>),  // This is the problem!
          typeof(MyUserControl));

    public Point<object> MyPoint
    {
        get { return (Point<???>) GetValue(PointDependencyProperty ); }
        set { SetValue(PointDependencyProperty, value); }
    }
}

As can be seen in the above code, I don't know how to register this property. Can it even be done? I tried object, but this is nullable so the compiler tells me:

The type 'object' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'MyNamespace.Point<T>'

Making the MyUserControl generic will become a problem for different reasons, so I don't want to go down that route either. Is there a way to do this?

Upvotes: 1

Views: 3232

Answers (2)

Patrick Hofman
Patrick Hofman

Reputation: 157098

That is because you define T to be a struct or something deriving that.

If you replace Point<object> with a struct, like Point<DateTime> it works:

public Point<DateTime> MyPoint
{
    get { return (Point<DateTime>) GetValue(PointDependencyProperty ); }
    set { SetValue(PointDependencyProperty, value); }
}

I wonder, do you really need T to be a struct? Can't you define Point<T> as:

class Point<T>
{
}

This will mean that T can be anything, and you can access it just the way you are used to, without the drawbacks of just using object or dynamic.

Upvotes: 0

JWP
JWP

Reputation: 6963

This one should do it for you. When you can't do something because of strong typing, think about containing that which you can't do, in this example MYPOINT contains the varying type object and the DP doesn't care.

public partial class MyUserControl : UserControl
{
    public MyUserControl()
    {
        InitializeComponent();
        var mp = new MyPoint();
        var mv = new MyType<string>("Now is the time");
        mp.MyType = mv;
        MyPoint = mp;
    }

    public static readonly DependencyProperty PointDependencyProperty =
        DependencyProperty.Register(
          "MyPoint",
          typeof(MyPoint),  // This is the problem!
          typeof(MyUserControl));

    public MyPoint MyPoint
    {
        get { return (MyPoint)GetValue(PointDependencyProperty); }
        set { SetValue(PointDependencyProperty, value); }
    }
}

public class MyPoint
{
    public dynamic MyType { get; set; }
}

public class MyType<T>
{
    public dynamic Myvalue { get; set; }

    public Point MyPoint { get; set; }

    public MyType(T value)
    {
        Myvalue = value;
    }
}

Upvotes: 2

Related Questions