gpt4 book ai didi

c# - 如何将 PropertyGrid 集合限制为 List

转载 作者:行者123 更新时间:2023-11-30 21:22:36 30 4
gpt4 key购买 nike

好的,我已经阅读了几个关于使用 PropertyGrid 和集合的问题。但是,我很难理解如何/如果 [TypeConverter]会为我工作。我已经阅读了 MSDN 发布的关于 blurb-age 的文章,坦率地说,对于这个可怜的自学成才的程序员来说,它有点欠缺。

所以,这就是我所拥有的。先来个合集:

[Serializable]
public List<ModuleData> Modules
{ get { return modules; } }

private List<ModuleData> modules;

集合中的对象:

[Serializable]
internal class ModuleData : IEquatable<ModuleData>
{
// simple data class with public properties
// to display in the propgrid control
}

我有一个 ListView 控件,其中包含描述 ModuleData 对象和 BatchData 对象的项。当我从 ListView 中选择 BatchData 项时,PropertyGrid 会按预期显示集合编辑器。有没有办法将集合编辑器限制为仅在 ListView 控件中列出的任何 ModuleData 项?理想情况下,我不希望将 BatchData 项(来自 ListView)添加到 BatchData 集合中 - 特别是因为该集合不是 BatchData 对象类型的“类型化”。

如果需要任何进一步的代码示例,我将非常乐意编辑其中的一些片段。

为清楚起见,ModuleData 是一个自定义类,它包含在指定程序集中实例化类所需的数据。它只包含字段和公共(public)/内部属性。我想做的是使用与属性网格控件组装的集合编辑器将 ModuleData 对象添加到 BatchData Module收藏。符合添加条件的ModuleData对象列在ListView控件中。

编辑:删除了 : List<ModuleData>继承。

更新:如果我要创建自定义集合编辑器,是否意味着我正在构建自己的自定义表单/对话框?然后基本上通过 UITypeEditor 的属性和继承向 propertygrid 提供信息以显示我的自定义集合对话框?

最佳答案

首先,我一点不确定为什么这既继承 ( : List<ModuleData> ) 又包装 ( public List<ModuleData> Modules { get { return this; } } ) 一个列表 - 单独一个应该没问题。

但是!要定义您可以创建的新对象的类型,您需要从 CollectionEditor 派生并覆盖 NewItemTypes property - 并将此编辑器与您的类型相关联。我一点不清楚您希望添加哪些对象,以及这是否是最佳设计。如果您想添加现有对象,您可能需要一个完全自定义的编辑器/uitypeeditor。


对于更新后的问题,这听起来确实像是自定义 UITypeEditor 的工作;这是一个使用下拉列表的版本;你也可以做弹出窗口(参见 svc 上的方法):

using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Collections;

static class Program
{
static void Main()
{
MyWrapper wrapper = new MyWrapper();
wrapper.Modules.Add(new ModuleData { ModuleId = 123 });
wrapper.Modules.Add(new ModuleData { ModuleId = 456 });
wrapper.Modules.Add(new ModuleData { ModuleId = 789 });

wrapper.Batches.Add(new BatchData(wrapper) { BatchId = 666 });
wrapper.Batches.Add(new BatchData(wrapper) { BatchId = 777 });

PropertyGrid props = new PropertyGrid { Dock = DockStyle.Fill };
ListView view = new ListView { Dock = DockStyle.Left };
foreach (ModuleData mod in wrapper.Modules) {
view.Items.Add(mod.ToString()).Tag = mod;
}
foreach (BatchData bat in wrapper.Batches) {
view.Items.Add(bat.ToString()).Tag = bat;
}
view.SelectedIndexChanged += delegate {
var sel = view.SelectedIndices;
if(sel.Count > 0) {
props.SelectedObject = view.Items[sel[0]].Tag;
}
};

Application.Run(new Form { Controls = { props, view} });
}
}

class MyWrapper
{
private List<ModuleData> modules = new List<ModuleData>();
public List<ModuleData> Modules { get { return modules; } }

private List<BatchData> batches = new List<BatchData>();
public List<BatchData> Batches { get { return batches; } }
}

class ModuleListEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.DropDown;
}
public override object EditValue(ITypeDescriptorContext context, System.IServiceProvider provider, object value)
{
IWindowsFormsEditorService svc;
IHasModules mods;
IList selectedModules;
if (context == null || (selectedModules = (IList)value) == null ||
(mods = context.Instance as IHasModules) == null
|| (svc = (IWindowsFormsEditorService)
provider.GetService(typeof(IWindowsFormsEditorService))) == null)
{
return value;
}
var available = mods.GetAvailableModules();
CheckedListBox chk = new CheckedListBox();
foreach(object item in available) {
bool selected = selectedModules.Contains(item);
chk.Items.Add(item, selected);
}
chk.ItemCheck += (s, a) =>
{
switch(a.NewValue) {
case CheckState.Checked:
selectedModules.Add(chk.Items[a.Index]);
break;
case CheckState.Unchecked:
selectedModules.Remove(chk.Items[a.Index]);
break;
}
};


svc.DropDownControl(chk);

return value;
}
public override bool IsDropDownResizable {
get {
return true;
}
}
}


interface IHasModules
{
ModuleData[] GetAvailableModules();
}

internal class BatchData : IHasModules {
private MyWrapper wrapper;
public BatchData(MyWrapper wrapper) {
this.wrapper = wrapper;
}
ModuleData[] IHasModules.GetAvailableModules() { return wrapper.Modules.ToArray(); }
[DisplayName("Batch ID")]
public int BatchId { get; set; }
private List<ModuleData> modules = new List<ModuleData>();
[Editor(typeof(ModuleListEditor), typeof(UITypeEditor))]
public List<ModuleData> Modules { get { return modules; } set { modules = value; } }

public override string ToString() {
return "Batch " + BatchId;
}
}

internal class ModuleData {
[DisplayName("Module ID")]
public int ModuleId { get; set; }

public override string ToString() {
return "Module " + ModuleId;
}
}

关于c# - 如何将 PropertyGrid 集合限制为 List<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2216209/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com