我想知道是否可以做某事。我有一个函数,它读取一个xml文件,并根据文件中的内容向表单添加控件。像这样的xml节点将创建它:
<Button Top="300" Left="100">Automatic</Button>
如果我在编辑模式下添加了任何控件,我有一个将控件保存回xml文件的函数。它工作正常,但我想知道是否有更简单的方法。目前,我有这样的代码来创建每个控件的实例:
switch (xmlchild.Name)
{
// Create a new control whose type is specified.
case "Button":
c = new Button();
break;
case "Label":
c = new Label();
break;
default:
c = null;
break;
}
但是,当我想使用更多类型的控件时,我需要不断添加开关案例。我可以做一些只需要文本并添加该类型控件的东西吗?我将不胜感激任何反馈!
谢谢!
答案 0 :(得分:2)
如果您控制XML文件的内容,那么是。你可以使用:
string fullNameSpace = "System.Windows.Controls.";
Type controlType = Type.GetType( fullNameSpace + xmlchild.Name );
if( controlType != null )
{
// get default constructor...
ConstructorInfo ctor = controlType.GetConstructor(Type.EmptyTypes);
object control = ctor.Invoke(null);
}
你也可以使用Activator
类来清理它:
object control = Activator.CreateInstance( "System.Windows.Presentation",
xmlchild.Name );
或者,如果您可以创建有效的XAML文件,则可以使用XamlReader来恢复控制树。
答案 1 :(得分:1)
您可以使用某些约定来保存自己的一些代码。基本上,使用反射来创建所需控件的实例,从XML传递代码。类似的东西:
Activator.CreateInstance(xmlchild.Name, ...)
只需填写正确的位,许多代码就会消失。
答案 2 :(得分:1)
听起来你正在寻找像Generics这样的东西。
您可以执行以下操作:
public static class ControlFactory
{
public static T CreateControl<T>() where T : Type, new()
{
return new T();
}
}
我还没有测试过这段代码,所以我会在测试时更新它。
答案 3 :(得分:1)
首先查看Activator类。然后,您可以将控件的类型名称存储为xml文件中的属性,并使用Activator类根据存储在当前xml元素的属性中的值创建实例(type =“fullTypeName”)。
此外,如果涉及属性,您可以考虑反射以基于属性名称在创建的实例上设置属性(即,您有一个控件实例 - 使用Activator类创建 - 并且您从Top属性分配值在xml中,可以使用反射获取/设置所创建实例的Top属性。
答案 4 :(得分:1)
可以像其他人描述的那样使用Reflection直接从其名称构造控件。但是,这种设计相当脆弱,如果XML文件是公开可见的,也可能引起安全问题,因为可以在运行时根据文件中的文本构造任意控件类型。这可能不是您特定应用的关注点。
我更喜欢使用Dictionary<string, Func<Control>>
的设计,其中您有代码注册一个回调,为每个名称创建控件。这为您提供了一些额外的灵活性(您可以动态交换控制构造方法或组合来自多个源的可用控件)并且看起来也更干净(交换机被一些'寄存器'调用替换,实际构造分解为单独的方法或(在简单的情况下)作为lambda表达式)。如果使用MyImprovedTextBox替换应用程序中的TextBox并希望以前的配置文件使用改进版本,这也允许向后兼容。