WPF通用控件 - 可能吗?

9
我想使用泛型创建自定义的WPF控件:
public class MyGenericTypeControl<T> : ItemsControl 
{   
   // ...
}

这个是否可行呢?在我的初步实验中,只要我尝试将此控件添加到某个位置,我就会立即获得设计时/编译时XAML错误。这并不令人惊讶,因为构建我的自定义控件需要XAML无法提供的额外信息。

有什么想法吗?

3个回答

6

使用 x:TypeArguments 的支持有限。

对于 XAML 2006 使用以及用于 WPF 应用程序的 XAML,以下是关于 x:TypeArguments 和 XAML 中通用类型使用的限制:

  • 只有 XAML 文件的根元素可以支持引用通用类型的通用 XAML 使用。
  • 根元素必须映射到至少具有一个类型参数的通用类型。例如,PageFunction<T>。页面功能是 WPF 中 XAML 通用使用支持的主要场景。
  • 通用的根元素 XAML 对象元素还必须声明使用 x:Class 的部分类。即使定义了 WPF 构建操作也是如此。
  • x:TypeArguments 不能引用嵌套的通用约束。

3

XAML 不支持泛型,你需要创建一个空的非泛型类,它继承自你的泛型控件,并在 XAML 中使用它。


我希望我的控件不知道正在使用的特定泛型类型。通过这种方法,非泛型派生类将需要告诉基类泛型类型是什么,而我不想这样做。 - kindohm
抱歉,唯一的解决方案是创建一个通用控件,将所有重要代码放入其中,然后使用不同类型参数继承它的一堆空类。 - Dean Chalk
@kindohm已经说得足够清楚了,这是不可能的,但我想指出没有太多理由这样做。你为什么需要那个?在WPF中,你已经可以修改很多东西了。DataTemplates提供了很大的灵活性,通过使用DataTemplateSelector和更改模板的Trigger,你可以创建几乎任何你想要的东西。 为什么你需要一个使用泛型参数的控件?为什么不用接口?如果你提供更多的代码,我们可能会给你一个更好的替代方案。 - dowhilefor
@DeanChalk - "XAML不支持泛型"并非完全正确。WPF在PageFunction中支持泛型。http://msdn.microsoft.com/en-us/library/ms615540(v=vs.110).aspx - user585968

3
你只能采用相反的方式实现(一个非泛型控件从一个泛型基类继承):
public class BaseControl<T> : Control
{
   // base implementation
}


public class MyControl : BaseControl<string>
{
   // ...
}

带有以下 XAML 的 MyControl

<local:MyControl x:Class="BaseControl"
                 x:TypeArguments="sys:String"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:local="clr-namespace:MyNamespace"
                 xmlns:sys="clr-namespace:System;assembly=System.Runtime">
    ....
<local:MyControl/>

请注意属性x:TypeArguments="....."。如果您的类型参数本身是泛型,那么您可以使用以下示例:

<local:MyControl x:Class="BaseControl"
                 x:TypeArguments="sys:Tuple(sys:String,sys:Int32)"
                 ...>

代码等价于:

public class MyControl : BaseControl<Tuple<string, int>>
{
   // ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接