DataGridView 列表柱子?

发布于 2024-09-14 22:31:14 字数 859 浏览 1 评论 0原文

我有一个 datagridView,它绑定到一个列表。该列表由我的类组成,其中包含 2 个公共属性、一个字符串名称和另一个列表自定义列表。如下所示:

public class MyClass2
{        
    public string Name
    { get; set;}


    public string Description
    {
        get;
        set;
    }
}

public class MyClass
{
    List<MyClass2> myList;

    public string Name
    {
        get;
        set;
    }

    public List<MyClass2> CustomList
    {
        get { return myList ?? (myList= new List<MyClass2>()); }
    }

}

然后在我的设计器页面中:

List<MyClass> myClassList = new List<MyClass>();
dataGridView.DataSource = myClassList;

现在,网格中显示的唯一列是 MyClass:Name 列,而 CustomList 列不会显示。我想要的是 CustomList 列显示并显示类似 "Collection" 的内容,并显示“...”按钮,并且单击它时会弹出“Collection Editor” 。

有谁知道这是否可行以及如何启用它?如果有教程或任何可以帮助我的东西,我也将不胜感激。谢谢。

I have a datagridView, that is bound to a List. This List is made up of my class which contains 2 public properties, a String Name, and another List CustomList. See below:

public class MyClass2
{        
    public string Name
    { get; set;}


    public string Description
    {
        get;
        set;
    }
}

public class MyClass
{
    List<MyClass2> myList;

    public string Name
    {
        get;
        set;
    }

    public List<MyClass2> CustomList
    {
        get { return myList ?? (myList= new List<MyClass2>()); }
    }

}

And then in my designer page:

List<MyClass> myClassList = new List<MyClass>();
dataGridView.DataSource = myClassList;

As it is right now, the only column that appears in the grid, is the MyClass:Name column, and the CustomList column does not show up. What I'd like is the CustomList column to show and to display something like "Collection" with the "..." button showing, and when it is clicked to have the "Collection Editor" to popup.

Does anyone know if this is possible and how to enable it? If there's a tutorial or anything that would help me out I'd appreciate that too. Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

扮仙女 2024-09-21 22:31:14

我认为使用泛型是一个干净的解决方案:

public class Sorter<T>: IComparer<T>
{
    public string Propiedad { get; set; }

    public Sorter(string propiedad)
    {
        this.Propiedad = propiedad;
    }

    public int Compare(T x, T y)
    {
        PropertyInfo property = x.GetType().GetProperty(this.Propiedad);
        if (property == null)
            throw new ApplicationException("El objeto no tiene la propiedad " + this.Propiedad);
        return Comparer.DefaultInvariant.Compare(property.GetValue(x, null), property.GetValue(y, null));
    }
}

用法示例:

string orderBy = "propertyName";
bool orderAsc = true;

List<MyExampleClass> myClassList = someMethod();

if (!string.IsNullOrEmpty(orderBy))
{
    myClassList.Sort(new Sorter<MyExampleClass>(orderBy));
    if (!orderAsc) myClassList.Reverse();
}

Using generics, I think, is a clean solution:

public class Sorter<T>: IComparer<T>
{
    public string Propiedad { get; set; }

    public Sorter(string propiedad)
    {
        this.Propiedad = propiedad;
    }

    public int Compare(T x, T y)
    {
        PropertyInfo property = x.GetType().GetProperty(this.Propiedad);
        if (property == null)
            throw new ApplicationException("El objeto no tiene la propiedad " + this.Propiedad);
        return Comparer.DefaultInvariant.Compare(property.GetValue(x, null), property.GetValue(y, null));
    }
}

Usage example:

string orderBy = "propertyName";
bool orderAsc = true;

List<MyExampleClass> myClassList = someMethod();

if (!string.IsNullOrEmpty(orderBy))
{
    myClassList.Sort(new Sorter<MyExampleClass>(orderBy));
    if (!orderAsc) myClassList.Reverse();
}
老街孤人 2024-09-21 22:31:14

简短回答:是的,您可以使用一些代码来做到这一点。

长答案:编写代码会很痛苦,因为您不仅必须知道 DataGridView 对自定义列的行为方式,而且还需要知道如何公开设计时间运行时的元素,这需要大量的管道。还必须了解有关 PropertyGrid 的广泛知识。

注意:这可能是一个写起来很有趣的组件。 (如果我有时间的话,我可能会真正解决这个问题)

Short answer: Yes, you can do it with some code.

Long answer: To write the code is gonna be a pain in the ass, as you would have to know not only how the DataGridView behaves with custom columns, but you would need to know how to expose design time elements at runtime, which requires quite a bit of plumbing. Extensive knowledge about the PropertyGrid must also be known.

Note: This might a fun component to write. (I might actually tackle it if I get some time)

南风几经秋 2024-09-21 22:31:14

因此,使用 Dave 发布的“按钮”方法以及我发现的一些实现 CollectionEditor 的代码,我可以在 MyClass2 中编​​辑 CustomList

这是我的解决方案,尽管不如我想要的那么干净:

将此类放在某处:

class MyHelper : IWindowsFormsEditorService, IServiceProvider, ITypeDescriptorContext
{
    public static void EditValue(IWin32Window owner, object component, string propertyName)
    {
        PropertyDescriptor prop = TypeDescriptor.GetProperties(component)[propertyName];
        if (prop == null) throw new ArgumentException("propertyName");
        UITypeEditor editor = (UITypeEditor)prop.GetEditor(typeof(UITypeEditor));
        MyHelper ctx = new MyHelper(owner, component, prop);
        if (editor != null && editor.GetEditStyle(ctx) == UITypeEditorEditStyle.Modal)
        {
            object value = prop.GetValue(component);
            value = editor.EditValue(ctx, ctx, value);
            if (!prop.IsReadOnly)
            {
                prop.SetValue(component, value);
            }
        }
    }
    private readonly IWin32Window owner;
    private readonly object component;
    private readonly PropertyDescriptor property;
    private MyHelper(IWin32Window owner, object component, PropertyDescriptor property)
    {
        this.owner = owner;
        this.component = component;
        this.property = property;
    }
    #region IWindowsFormsEditorService Members

    public void CloseDropDown()
    {
        throw new NotImplementedException();
    }

    public void DropDownControl(System.Windows.Forms.Control control)
    {
        throw new NotImplementedException();
    }

    public System.Windows.Forms.DialogResult ShowDialog(System.Windows.Forms.Form dialog)
    {
        return dialog.ShowDialog(owner);
    }

    #endregion

    #region IServiceProvider Members

    public object GetService(Type serviceType)
    {
        return serviceType == typeof(IWindowsFormsEditorService) ? this : null;
    }

    #endregion

    #region ITypeDescriptorContext Members

    IContainer ITypeDescriptorContext.Container
    {
        get { return null; }
    }

    object ITypeDescriptorContext.Instance
    {
        get { return component; }
    }

    void ITypeDescriptorContext.OnComponentChanged()
    { }

    bool ITypeDescriptorContext.OnComponentChanging()
    {
        return true;
    }

    PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor
    {
        get { return property; }
    }

    #endregion

添加将按钮列添加到数据网格:

DataGridViewButtonColumn butt = new DataGridViewButtonColumn();
butt.HeaderText = "CustomList";
butt.Name = "CustomList";
butt.Text = "Edit CustomList...";
butt.UseColumnTextForButtonValue = true;

dataGridView.Columns.Add(butt);
dataGridView.CellClick += new DataGridViewCellEventHandler(dataGridView_CellClick);

然后在单元格单击的按钮处理程序中调用它。

if (e.RowIndex < 0 || e.ColumnIndex != dataGridView.Columns["CustomList"].Index)
            return;

//get the name of this column
string name = (string)dataGridView[dataGridView.Columns["Name"].Index, e.RowIndex].Value;

var myClassObject= myClassList.Find(o => o.Name == name);

MyHelper.EditValue(this, myClassObject, "CustomList");

我仍然有兴趣听到其他方法,而不必实现我自己的 CollectionEditor。我仍然有兴趣让它看起来更像 TabControl 用于在 PropertyGrid 中添加 TabPages 的内容...通过显示“...”按钮...但这现在可能有效。

So using the 'button' approach posted by Dave, and some code that I found that implements the CollectionEditor, I can edit the CustomList in MyClass2

Here's my solution, although not quite as clean as I'd like:

Put this class somewhere:

class MyHelper : IWindowsFormsEditorService, IServiceProvider, ITypeDescriptorContext
{
    public static void EditValue(IWin32Window owner, object component, string propertyName)
    {
        PropertyDescriptor prop = TypeDescriptor.GetProperties(component)[propertyName];
        if (prop == null) throw new ArgumentException("propertyName");
        UITypeEditor editor = (UITypeEditor)prop.GetEditor(typeof(UITypeEditor));
        MyHelper ctx = new MyHelper(owner, component, prop);
        if (editor != null && editor.GetEditStyle(ctx) == UITypeEditorEditStyle.Modal)
        {
            object value = prop.GetValue(component);
            value = editor.EditValue(ctx, ctx, value);
            if (!prop.IsReadOnly)
            {
                prop.SetValue(component, value);
            }
        }
    }
    private readonly IWin32Window owner;
    private readonly object component;
    private readonly PropertyDescriptor property;
    private MyHelper(IWin32Window owner, object component, PropertyDescriptor property)
    {
        this.owner = owner;
        this.component = component;
        this.property = property;
    }
    #region IWindowsFormsEditorService Members

    public void CloseDropDown()
    {
        throw new NotImplementedException();
    }

    public void DropDownControl(System.Windows.Forms.Control control)
    {
        throw new NotImplementedException();
    }

    public System.Windows.Forms.DialogResult ShowDialog(System.Windows.Forms.Form dialog)
    {
        return dialog.ShowDialog(owner);
    }

    #endregion

    #region IServiceProvider Members

    public object GetService(Type serviceType)
    {
        return serviceType == typeof(IWindowsFormsEditorService) ? this : null;
    }

    #endregion

    #region ITypeDescriptorContext Members

    IContainer ITypeDescriptorContext.Container
    {
        get { return null; }
    }

    object ITypeDescriptorContext.Instance
    {
        get { return component; }
    }

    void ITypeDescriptorContext.OnComponentChanged()
    { }

    bool ITypeDescriptorContext.OnComponentChanging()
    {
        return true;
    }

    PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor
    {
        get { return property; }
    }

    #endregion

Add a button column to the data grid:

DataGridViewButtonColumn butt = new DataGridViewButtonColumn();
butt.HeaderText = "CustomList";
butt.Name = "CustomList";
butt.Text = "Edit CustomList...";
butt.UseColumnTextForButtonValue = true;

dataGridView.Columns.Add(butt);
dataGridView.CellClick += new DataGridViewCellEventHandler(dataGridView_CellClick);

Then call it in the button handler of the cell click.

if (e.RowIndex < 0 || e.ColumnIndex != dataGridView.Columns["CustomList"].Index)
            return;

//get the name of this column
string name = (string)dataGridView[dataGridView.Columns["Name"].Index, e.RowIndex].Value;

var myClassObject= myClassList.Find(o => o.Name == name);

MyHelper.EditValue(this, myClassObject, "CustomList");

I'd still be interested in hearing other approaches, and not having to implement my own CollectionEditor. And I'm still interested in having it look more like what the TabControl uses to add TabPages in the PropertyGrid...by displaying the "..." button...but this might work for now.

南渊 2024-09-21 22:31:14

您想要做的是添加一个带有按钮的列模板:

http://geekswithblogs.net/carmelhl/archive/2008/11/11/126942.aspx

在按钮的处理程序中,从集合中获取选定的 MyClass 项并绑定其将属性列表到弹出窗口中的网格中。

What you want to do is add a column template with a button in it:

http://geekswithblogs.net/carmelhl/archive/2008/11/11/126942.aspx

In the handler for the button, get the selected MyClass item from the collection and bind its list property to a grid in your popup.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文