从形状派生的类会产生转换错误

时间:2018-06-24 11:53:45

标签: c# uwp

我在UWP项目中有一个类,该类派生自Windows.UI.Xaml.Shapes.Shape:

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

    }
}

当我尝试在mainPage.cs中实例化此类的新成员时,我收到一个InvalidCastException,如下所示:

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)

这是mainPage.cs中的代码

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

但也不起作用。据我了解,应该可以从派生类访问Shape的受保护构造函数,所以发生了什么?从Windows.UI.Xaml.Frameworkelemnt派生出来也可以做同样的事情。

3 个答案:

答案 0 :(得分:1)

TLDR;没有严重的伤害是不可能的。但是...有可能。

我从重现问题开始,这是证明它的堆栈跟踪:

   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()

您会看到xaml元素(App1_XamlTypeInfo)的类型提供程序是在运行时生成的,因此您无法使用自定义代码覆盖那些[Factory | Instance Creation | Builder]方法。

甚至没有尝试在Hex类中创建到Shape类型的隐式转换也可以解决该问题,这显然是C#的局限性,即您无法进行从子类到基类的自定义隐式转换,因为“已经编译的代码”或其他任何内容:(

另一种方法可能是优先考虑封装而不是继承,您将需要重新实现/暴露Shape类,并操纵其内部Shape实例,但是限制是您不能从WPF实现IShape和IShape2接口,因为它们被标记为内部。

据我所知,剩下的唯一选择就是修改WPF源代码,并分发该代码...我不知道与执行此类操作相关的许可问题。有关需要更改的类,请参见https://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Shapes/Shape.cs,或者仅包含您自己的派生类型(例如Ellipse),而https://referencesource.microsoft.com/#PresentationFramework/PresentationFramework.csproj仅指出构建起来很容易< em>需要引用。

希望有人来证明我错了...

答案 1 :(得分:1)

我也不明白。这很烦人,但显然您不能像预期的那样从Shape派生(并且应该能够这样做。)相反,您必须从Path继承并以这种方式添加路径。我将在此处针对SO链接另一个答案,该答案比重复说明的要好得多。

Answered already on SO

答案 2 :(得分:1)

  

当我尝试在mainPage.cs中实例化此类的新成员时   我收到一个InvalidCastException,如下所示:

this.state = {
  dob: moment(props.dob)
};

<DatePicker
    date={this.state.dob}
    onDateChange={this.onDateChange}
    ... other attributes
/>

<input
    type="text"
    value={this.state.dob}
    onChange={this.onInputDateChange}
    ... other attributes
/>

onDateChange = (dob) => {
    if (dob) {
      this.setState(() => ({ dob }));
    }
};

onInputDateChange = (e) => {
    const dob = e.target.value;
    if (dob) {
      this.setState(() => ({ dob }));
    }
};

感谢您的反馈。我们完全理解,这种例外情况可能会引起混乱。

事实是,即使未密封Shape,也无法创建以这种方式创建的自定义形状。

要绘制自定义形状,请使用现有的Shape类型。

例如,可以使用具有6个顶点的多边形来轻松创建十六进制形状:

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)

对于更复杂的形状,客户可以改用Path类,如下所述: https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/shapes#path

如果需要,您可以在自定义控件中包装任何形状,例如使用UserControl: https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.usercontrol