Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class derived from shape gives cast error

Tags:

c#

uwp

I have a class in a UWP Project that derives from Windows.UI.Xaml.Shapes.Shape:

public class Hex : Windows.UI.Xaml.Shapes.Shape
{
    public Hex()
    {

    }
}

When I tried to instantiate a new memeber of this class in mainPage.cs I get an InvalidCastException as following:

System.InvalidCastException: Specified cast is not valid.
       at Windows.UI.Xaml.Shapes.Shape..ctor()
       at App1.Hex..ctor()
       at App1.MainPage.Button_Click(Object sender, RoutedEventArgs e)

Here is the code from mainPage.cs

private void Button_Click(object sender, RoutedEventArgs e)
{
    var h = new Hex();
    h.Width = 20;
}

but doesn't work neither. As I understand the protected constructor of Shape should be able to be accessed from a derived class, so what's happening? Doing the same thing with deriving from Windows.UI.Xaml.Frameworkelemnt works without problems.

like image 785
Mansly Avatar asked Jun 24 '18 11:06

Mansly


Video Answer


2 Answers

TLDR; It's not possible without some serious hurt. But... IT IS POSSIBLE.

I started out by reproducing the problem, here's the stack trace to prove it:

   at Windows.UI.Xaml.Shapes.Shape..ctor()
   at App1.Hex..ctor()
   at App1.App1_XamlTypeInfo.XamlTypeInfoProvider.Activate_0_Hex()
   at App1.App1_XamlTypeInfo.XamlUserType.ActivateInstance()

You can see that the type providers for the xaml elements (App1_XamlTypeInfo) are generated at run-time, thus you cannot override those [Factory|Instance Creation|Builder] methods with customised code.

Not even an attempt to create an implicit conversion in the Hex class to the Shape type could fix it, apparently a limitation of C# that you cannot make a custom implicit conversion from sub-class to base-class, because "it changes already compiled code" or whatever :(

Another route could have been to favour encapsulation over inheritance, you'd be required to re-implement/expose the Shape class in all its glory and manipulate an internal Shape instance, however there'll be a limitation in that you cannot implement the IShape and IShape2 interfaces from WPF, because they're marked internal.

As far as I can tell, the only option left is to modify the WPF source code, and distribute that... I have no idea on licensing issues related to doing such things. See https://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Shapes/Shape.cs for the class that you'd need to change, or just include your own derived type (like Ellipse), and https://referencesource.microsoft.com/#PresentationFramework/PresentationFramework.csproj just to point out that it's quite easy to build citation needed.

Hopefully someone else comes along and proves me wrong...

like image 171
Dan Rayson Avatar answered Sep 22 '22 12:09

Dan Rayson


I don't understand this either; it's quite annoying but apparently you can't derive from Shape as you'd expect (and should be able to do.) Instead you have to inherit from Path and add the paths that way. I'll link another answer here on SO that explains it better rather than duplicate.

Answered already on SO

like image 44
Michael Puckett II Avatar answered Sep 20 '22 12:09

Michael Puckett II