1、通过XML反射生成窗体,如果将反射的组件(非可视组件IComponet)添加到窗体中
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Reflection;
namespace ReflectionLoadFormDemo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//手动添加控件
TextBox textBox = new TextBox();
textBox.Name = "txtTest";
textBox.Location = new Point(20, 20);
textBox.Text = "手动添加";
this.Controls.Add(textBox);
//通过反射操作来添加控件
//System.Windows.Forms所在的dll文件路径
Assembly assembly = Assembly.LoadFile(@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Windows.Forms.dll");
Type type = assembly.GetType("System.Windows.Forms.TextBox");
//调用实例化方法(非静态方法)需要创建类型的一个实例
object instanceObject = Activator.CreateInstance(type);
//Name属性
PropertyInfo propertyInfoName = type.GetProperty("Name");
propertyInfoName.SetValue(instanceObject, "txtTest");
//Location属性
PropertyInfo propertyInfoLocation = type.GetProperty("Location");
propertyInfoLocation.SetValue(instanceObject, new Point(60, 60));
//Text属性
PropertyInfo propertyInfoText = type.GetProperty("Text");
propertyInfoText.SetValue(instanceObject, "反射添加控件");
if (instanceObject is TextBox)
{
this.Controls.Add((TextBox)instanceObject);
}
}
}
}
运行示例:
在你的xml文件中,是否存在这样的节点
<TextBox>
<Name>txtTest</Name>
<Location><X>60</X><Y>50</Y></Location>
<Text>Hello</Text>
</TextBox>
读取xml节点,请参考博客【C#读取配置文件Ini,json,xml并绑定到树图上】 https://blog.csdn.net/ylq1045/article/details/108283457
instance = Activator.CreateInstance(type);
if (typeof(Form).IsAssignableFrom(type))
{
if (!isDesiger)
{
frm = (Form)Activator.CreateInstance(type);
}
else
instance = host.CreateComponent(type, nameAttr.Value);
}
else
{
if (!isDesiger)
{
if (instance is Control)
frm.Controls.Add((Control)instance);
else
{
if (instance is Component)
{
frm.Container.Add((IComponent)instance);
}
}
}
else
instance = host.CreateComponent(type, nameAttr.Value);
}
frm.Container 始终为null,该属性是只读属性
当前要插入的是 IComponent
组件 以System.IO.Ports.SerialPort 为例,不是一个控件 因此 不能使用 controls.add(...)
模仿如下代码:
/// <summary>
/// 添加一个组件
/// </summary>
private IComponent AddComponent()
{
//组件所在的dll
Assembly assembly = Assembly.LoadFile(@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.dll");
Type type = assembly.GetType("System.IO.Ports.SerialPort");
object instanceObject = Activator.CreateInstance(type);
//PortName属性
PropertyInfo propertyInfoLocation = type.GetProperty("PortName");
propertyInfoLocation.SetValue(instanceObject, "COM1");
//Text属性
PropertyInfo propertyInfoText = type.GetProperty("BaudRate");
propertyInfoText.SetValue(instanceObject, 9600);
return (IComponent)instanceObject;
}
使用时 如下:
//只是一个字段 不能添加到窗体的控件中
IComponent component = AddComponent();
if (component is System.IO.Ports.SerialPort)
{
MessageBox.Show($"{((System.IO.Ports.SerialPort)component).BaudRate}");
}
控件Control一定是一个组件,当某些组件可能不是控件。不是控件时,只能做为Form类的成员字段
bizdbobj1这个组件 就是窗体(类)的一个成员字段 field 。你看下 .designer.cs的代码就明白了
本质保存一个BizPageFrm类下面的字段bizdbobj1而已
bizdbobj1其实就是继承datatable,这个组件不一定会是bizpagefrm,只是这个时候恰好是他的一个属性字段
this.components = new System.ComponentModel.Container();
this.bizDbObj1 = new Nif.Controls.BizDbObj(this.components);
其实我就想把这种情况如何通过XML反射到当前窗体中