【发布时间】:2021-02-25 16:25:25
【问题描述】:
在自定义 WPF 控件中工作,我们需要允许用户将新对象添加到列表中(类似于 IsEditable = true 时的 ComboBox)。
ItemsSource 是 ObservableCollection
当用户输入一个字符串时,控件需要创建一个新的T对象并将其添加到列表中。
我们有一个方法可以从 ItemsSource 对象中判断 T 是什么类型,然后使用 Activator.CreateInstance() 创建一个 T:
private Type _typ;
public void AddSomething(object o)
{
var iCollection = o as ICollection;
if (iCollection != null)
{
dynamic oc = iCollection;
_typ = GetGenericType(oc);
Debug.WriteLine($" ICollection<T> T type: {_typ}");
var thng = Activator.CreateInstance(_typ);
Debug.WriteLine($" thng Type: {thng.GetType()}");
ItemsSourceClass.Things.Add(thng as _typ);
// Compile time error:
CS0246 The type or namespace name '_typ' could not be found (are you missing a using directive or an assembly reference?)
/* snip */
这一切都按预期工作 - thng 是 T 的一个新实例 - 直到我们尝试将新对象添加到 ItemsSource 集合。
由于 Activator.CreateInstance(Type t) 返回 object,看来我们需要将 thng 转换为 T 以添加到 ObservableCollection
我们尝试了各种方法来让 ItemsSource 集合相信 thng 是正确的类型,但还没有找到一种有效的方法。
我们缺少什么?
更新
我们添加了一个依赖变量:
public static readonly DependencyProperty ListObjectTypeProperty =
DependencyProperty.Register("ListObjectType", typeof(Type), typeof(AutoCompleteComboBox));
在 xaml 中:
ListObjectType="{x:Type local:SimpleClass}"
ListObjectTypeProperty 的这种用法传递了正确的对象,但它仍然是类型 object:
这样做的结果相同:
var assemName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
var thng = Activator.CreateInstance(assemName, ListObjectType.FullName);
var thng2 = thng.Unwrap();
【问题讨论】:
-
为什么包含类也不是泛型的,那么你可以说
var thng = new T();?你不能做as MyTypeVariable,它是无效的 -
ItemsSourceClass.Things的类型是什么? -
@Charlieface 这段代码在一个控件中,可以交给一个 ICollection
,其中 T 几乎可以是任何东西。 -
@canton7 public class SimpleClass { public string Name {get;设置;}公共字符串颜色{get;集;}公共整数计数{get;设置;}
-
@Cat 你的
SimpleClass上没有Add方法...ItemsSourceClass.Things的类型是什么?
标签: c# observablecollection activator