C# 存储和使用具有特定限制的泛型类型的数据类型?
我觉得这应该很容易,但今天早上我的大脑出现了问题 我有一个自定义C# 存储和使用具有特定限制的泛型类型的数据类型?,c#,winforms,.net-3.5,C#,Winforms,.net 3.5,我觉得这应该很容易,但今天早上我的大脑出现了问题 我有一个自定义UserControl绑定到自定义ItemsSource。我想根据用户定义的绘制项目的方式,使用匹配的控件将其设置为绘制每个项目 例如,我希望能够从使用控件的类中执行此操作 var data = new List<object>(); data.Add(new MyClassA()); data.Add(new MyClassB()); data.Add(new MyClassB()); myCustomControl
UserControl
绑定到自定义ItemsSource
。我想根据用户定义的绘制项目的方式,使用匹配的控件
将其设置为绘制每个项目
例如,我希望能够从使用控件的类中执行此操作
var data = new List<object>();
data.Add(new MyClassA());
data.Add(new MyClassB());
data.Add(new MyClassB());
myCustomControl.ItemsSource = myObjectArray;
myCustomControl.ResourceLibrary = {
{ MyClassA, ctlClassA },
{ MyClassB, ctlClassB }
}
我可以为ResourceLibrary
使用什么样的数据类型来执行此操作?还是有更好的方法来完成这项任务
我还希望能够将传入的类型限制为只允许类型where T:Control,new()
我在最基本的层面上使用WinForms、C#和.Net 3.5,我认为这样做可能会有所帮助:
public class DataTemplateManager
{
private readonly Dictionary<Type, Type> dataTemplates = new Dictionary<Type, Type>();
public void Add<TModel, TView>() where TView : Control, new()
{
dataTemplates.Add(typeof (TModel), typeof (TView));
}
public void Add(Type modelType, Type viewType)
{
if (!typeof (Control).IsAssignableFrom(viewType))
throw new InvalidOperationException("viewType must derive from System.Windows.Forms.Control");
dataTemplates.Add(modelType, viewType);
}
public Control Resolve(object model)
{
if (model == null)
return null;
var type = model.GetType();
if (!dataTemplates.ContainsKey(type))
return null;
var viewType = dataTemplates[type];
var control = Activator.CreateInstance(viewType);
return control as Control;
}
}
然后你可以这样使用:
myControl1.DataTemplateManager.Add<MyModel1, MyView1>();
myControl1.DataTemplateManager.Add<MyModel2, MyView2>();
myControl1.DataTemplateManager.Add<MyModel3, MyView3>();
此外,我还可以想到一些非常有用的功能,比如IBinder
的概念,它将负责对ctl做一些事情。
部分:
public interface IBinder<TModel,TView>
{
void Bind(TModel model, TView view);
}
public class MyBinder: IBinder<MyModel1,MyView1>
{
public void Bind(MyModel1 model, MyView1 view)
{
view.SomeProperty = model.SomeOtherProperty;
//.. And so on.
}
}
公共接口IBinder
{
无效绑定(TModel模型、TView视图);
}
公共类MyBinder:IBinder
{
公共void绑定(MyModel1模型,MyView1视图)
{
view.SomeProperty=model.SomeOtherProperty;
//…等等。
}
}
然后:
myControl.DataTemplateManager.AddBinder();
并在Resolve()
方法中使用它
请注意,这不处理继承或泛型。如果您需要支持这些场景,您的想法会变得更复杂一些,但它仍然是可行的
顺便说一句,我试着让这个尽可能抽象。否则人们可能会认为我在编写winforms代码…您的问题之一是
var ctl=new ctlType()
,C#不做虚拟构造函数。使用MVVM和Caliburn,将其替换/包装为MyClassAViewModel
和MyClassAView
,整个东西就变成了automagic。@Henkholtman我希望我可以使用WPF来实现这一点,但它是WinForms和.Net 3.5Heh。。您正在winforms中实现一个ItemsControl
?太酷了。。代码是专有的吗?否则,如果你能分享,那就太棒了。@HighCore我不想尝试任何这么高级的东西。。。我只想要一个可绑定的TabControl。似乎对WinForms的要求有点太多了=/哇,干得不错!如果可能的话,我会给你一些额外的赏金代表。:)
myControl1.DataTemplateManager.Add<MyModel1, MyView1>();
myControl1.DataTemplateManager.Add<MyModel2, MyView2>();
myControl1.DataTemplateManager.Add<MyModel3, MyView3>();
foreach(var item in ItemsSource)
{
var ctl = this.DataTemplateManager.Resolve(item);
//.. do something with ctl
}
public interface IBinder<TModel,TView>
{
void Bind(TModel model, TView view);
}
public class MyBinder: IBinder<MyModel1,MyView1>
{
public void Bind(MyModel1 model, MyView1 view)
{
view.SomeProperty = model.SomeOtherProperty;
//.. And so on.
}
}
myControl.DataTemplateManager.AddBinder<TModel1,TView1,MyBinder>();