CheckedListBox 并将对象属性绑定到项目

发布于 2024-11-30 05:04:35 字数 725 浏览 3 评论 0原文

我很好奇是否有一种简单的方法将类的属性绑定到 CheckedListBox 的各个项目。有几个组件(Telerik/DevExpress)提供 PropertyEditor 网格,但我希望在 CheckedListBox 中实现。

IE:

public class MyItem
{
    public bool Property1
    {
        get;
        set;
    }

    public bool Property2
    {
        get;
        set;
    }

    public bool Property3
    {
        get;
        set;
    }
}

当向 CheckedListBox 添加项目时,我希望有某种方法可以让我这样做:

this.AddCheckListBoxItem("Property A", this.myItem.Property1);
this.AddCheckListBoxItem("Property B", this.myItem.Property2);
this.AddCheckListBoxItem("Property C", this.myItem.Property3);

第一个参数是 CheckedListBox 中的显示名称。

然后,在检查状态发生任何更改时,布尔值都会自动更新,无需进一步的代码。

I'm curious if there is a simple way to bind properties of a class to individual items of a CheckedListBox. There are several components out there (Telerik/DevExpress) that provide PropertyEditor grids, but I'm looking to do it in a CheckedListBox.

IE:

public class MyItem
{
    public bool Property1
    {
        get;
        set;
    }

    public bool Property2
    {
        get;
        set;
    }

    public bool Property3
    {
        get;
        set;
    }
}

And when adding items to the CheckedListBox, I'd like to have some sort of method that lets me do:

this.AddCheckListBoxItem("Property A", this.myItem.Property1);
this.AddCheckListBoxItem("Property B", this.myItem.Property2);
this.AddCheckListBoxItem("Property C", this.myItem.Property3);

the first parameter being the display name within the CheckedListBox.

Then throughout any changes to the checkstate, the bool values would automatically be updated without further code.

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

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

发布评论

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

评论(2

错々过的事 2024-12-07 05:04:35

目前没有任何简单/简单的方法来获得您正在寻找的功能。
正如评论中一样,我能想到的最接近的解决方案是使用反射。

如果您设法构建一个具有此功能的帮助器类,请在此处发布,因为我也发现这很有用。

Currently there isn't any easy/simple way to get the functionallity you are looking for.
As in the comments the nearest solution I can think of would be to use reflection.

If you manage to build a helper class that has this functionallity, please post here as I would also find that usefull.

焚却相思 2024-12-07 05:04:35

我已经按照 @Jethro 的建议使用反射创建了一个解决方案。我在类定义中使用了泛型,但我还没有实现任何使用它们的东西。总而言之,基本上使用反射,我将单个对象及其布尔属性绑定到标准 CheckedListBox 中的各个项目。这很好,因为它不需要编写代码来设置属性值并在保存数据时获取它们,因为反射会处理这个问题。

我创建了一个表单,并向其中添加了一个 CheckedListBox 和一个按钮。这是代码方面。

using System;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

/// <summary>
/// The main form.
/// </summary>
public partial class Form1 : Form
{
    /// <summary>
    /// The checked list box property helper.
    /// </summary>
    private CheckedListBoxPropertyHelper<MyItem> helper;

    /// <summary>
    /// My object to bind to the checked list box.
    /// </summary>
    private MyItem myObjectDataSource;

    /// <summary>
    /// Initializes a new instance of the <see cref="Form1"/> class.
    /// </summary>
    public Form1()
    {
        this.InitializeComponent();

        this.myObjectDataSource = new MyItem();
        this.helper = new CheckedListBoxPropertyHelper<MyItem>(this.checkedListBox1, this.myObjectDataSource, true);

        this.helper.AddCheckListBoxItem(new CheckedPropertyItem("Property One", "Property1"));
        this.helper.AddCheckListBoxItem(new CheckedPropertyItem("Property Two", "Property2"));
        this.helper.AddCheckListBoxItem(new CheckedPropertyItem("Property Three", "Property3"));
    }

    /// <summary>
    /// Handles the Click event of the Button1 control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void Button1_Click(object sender, EventArgs e)
    {
        // In the constructor
        // if we instantiated: this.helper = new CheckedListBoxPropertyHelper<MyItem>(this.checkedListBox1, this.myObjectDataSource, true);
        // as: this.helper = new CheckedListBoxPropertyHelper<MyItem>(this.checkedListBox1, this.myObjectDataSource, false);
        // changing the last bindImmediate property to false, the changes to the checkboxes wouldn't take effect immediately
        // on the underlying object, you need to call this.helper.CommitChanges() at which point the changes
        // will be made to the datasource object.

        // this.helper.CommitChanges();

        Console.WriteLine(this.myObjectDataSource.Property1.ToString());
        Console.WriteLine(this.myObjectDataSource.Property2.ToString());
        Console.WriteLine(this.myObjectDataSource.Property3.ToString());
    }
}

/// <summary>
/// My item.
/// </summary>
public class MyItem
{
    /// <summary>
    /// Gets or sets a value indicating whether this <see cref="MyItem"/> is property1.
    /// </summary>
    /// <value><c>true</c> if property1; otherwise, <c>false</c>.</value>
    public bool Property1
    {
        get;
        set;
    }

    /// <summary>
    /// Gets or sets a value indicating whether this <see cref="MyItem"/> is property2.
    /// </summary>
    /// <value><c>true</c> if property2; otherwise, <c>false</c>.</value>
    public bool Property2
    {
        get;
        set;
    }

    /// <summary>
    /// Gets or sets a value indicating whether this <see cref="MyItem"/> is property3.
    /// </summary>
    /// <value><c>true</c> if property3; otherwise, <c>false</c>.</value>
    public bool Property3
    {
        get;
        set;
    }
}

/// <summary>
/// The checked list box property helper. This binds datasource properties to checkedlistbox items.
/// </summary>
public class CheckedListBoxPropertyHelper<T> where T : class
{
    /// <summary>
    /// The checked list box.
    /// </summary>
    private CheckedListBox checkedListBox;

    /// <summary>
    /// The property info.
    /// </summary>
    private PropertyInfo[] PropertyInfo;

    /// <summary>
    /// Initializes a new instance of the <see cref="CheckedListBoxPropertyHelper"/> class.
    /// </summary>
    /// <param name="checkedListBox">The checked list box.</param>
    /// <param name="dataSource">The data source.</param>
    /// <param name="bindImmediate">if set to <c>true</c> [bind immediate].</param>
    public CheckedListBoxPropertyHelper(CheckedListBox checkedListBox, T dataSource, bool bindImmediate)
    {
        this.checkedListBox = checkedListBox;
        this.DataSource = dataSource;
        this.PropertyInfo = this.DataSource.GetType().GetProperties();
        this.BindImmediate = bindImmediate;
        this.checkedListBox.ItemCheck += new ItemCheckEventHandler(CheckedListBox_ItemCheck);
    }

    /// <summary>
    /// The data source.
    /// </summary>
    public T DataSource
    {
        get;
        private set;
    }

    /// <summary>
    /// Gets or sets a value indicating whether to [bind immediately] to the datasource object.
    /// </summary>
    /// <value><c>true</c> if [bind immediately]; otherwise, <c>false</c>.</value>
    public bool BindImmediate
    {
        get;
        set;
    }

    /// <summary>
    /// Commits the changes.
    /// </summary>
    public void CommitChanges()
    {
        if (!this.BindImmediate)
        {
            for (int i = 0; i < this.checkedListBox.Items.Count; i++)
            {
                CheckedPropertyItem checkedItem = this.checkedListBox.Items[i] as CheckedPropertyItem;
                this.SetChecked(this.checkedListBox.GetItemChecked(i), checkedItem);
            }
        }
        else
        {
            throw new InvalidOperationException("You cannot commit changes when bind immediate is on.");
        }
    }

    /// <summary>
    /// Adds the check list box item.
    /// </summary>
    /// <param name="item">The item.</param>
    public void AddCheckListBoxItem(CheckedPropertyItem item)
    {
        PropertyInfo info = this.GetPropertyInfo(item.PropertyName);
        bool isChecked = false;

        if (info != null)
        {
            isChecked = (bool)info.GetValue(this.DataSource, null);
        }

        this.checkedListBox.Items.Add(item, isChecked);
    }

    /// <summary>
    /// Handles the ItemCheck event of the CheckedListBox control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Windows.Forms.ItemCheckEventArgs"/> instance containing the event data.</param>
    private void CheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
    {
        if (BindImmediate)
        {
            CheckedListBox clb = sender as CheckedListBox;
            CheckedPropertyItem checkedItem = clb.Items[e.Index] as CheckedPropertyItem;

            this.SetChecked(
                e.NewValue == CheckState.Checked ? true : false,
                 checkedItem);
        }
    }

    /// <summary>
    /// Sets the checked.
    /// </summary>
    /// <param name="isChecked">if set to <c>true</c> [is checked].</param>
    /// <param name="clb">The CLB.</param>
    private void SetChecked(bool isChecked, CheckedPropertyItem item)
    {
        PropertyInfo info = this.GetPropertyInfo(item.PropertyName);

        if (info.CanWrite)
        {
            info.SetValue(this.DataSource, isChecked, null);
        }
    }

    /// <summary>
    /// Gets the property info.
    /// </summary>
    /// <param name="propertyName">Name of the property.</param>
    /// <returns></returns>
    private PropertyInfo GetPropertyInfo(string propertyName)
    {
        return this.PropertyInfo
            .Where(c => c.Name == propertyName)
            .SingleOrDefault();
    }
}

/// <summary>
/// Checked Property Item binding.
/// </summary>
public class CheckedPropertyItem
{
    /// <summary>
    /// Initializes a new instance of the <see cref="CheckedPropertyItem"/> class.
    /// </summary>
    /// <param name="title">The title.</param>
    /// <param name="propertyName">Name of the property.</param>
    public CheckedPropertyItem(string title, string propertyName)
    {
        this.Title = title;
        this.PropertyName = propertyName;
    }

    /// <summary>
    /// Gets or sets the title.
    /// </summary>
    /// <value>The title.</value>
    public string Title
    {
        get;
        private set;
    }

    /// <summary>
    /// Gets the name of the property.
    /// </summary>
    public string PropertyName
    {
        get;
        private set;
    }

    /// <summary>
    /// Returns a <see cref="System.String"/> that represents this instance.
    /// </summary>
    /// <returns>A <see cref="System.String"/> that represents this instance.</returns>
    public override string ToString()
    {
        return this.Title;
    }
}

I've created a solution using reflection as suggested by @Jethro. I used generics in the class definition, but I didn't implement anything that uses them yet. To summarize, basically using reflection, I've bound a single object and it's boolean properties to individual items within a standard CheckedListBox. It's nice as it doesn't require having to code to set the property values and get them when saving data, as the reflection takes care of this.

I created a Form, and added a CheckedListBox to it, and a button. Here's the code side.

using System;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

/// <summary>
/// The main form.
/// </summary>
public partial class Form1 : Form
{
    /// <summary>
    /// The checked list box property helper.
    /// </summary>
    private CheckedListBoxPropertyHelper<MyItem> helper;

    /// <summary>
    /// My object to bind to the checked list box.
    /// </summary>
    private MyItem myObjectDataSource;

    /// <summary>
    /// Initializes a new instance of the <see cref="Form1"/> class.
    /// </summary>
    public Form1()
    {
        this.InitializeComponent();

        this.myObjectDataSource = new MyItem();
        this.helper = new CheckedListBoxPropertyHelper<MyItem>(this.checkedListBox1, this.myObjectDataSource, true);

        this.helper.AddCheckListBoxItem(new CheckedPropertyItem("Property One", "Property1"));
        this.helper.AddCheckListBoxItem(new CheckedPropertyItem("Property Two", "Property2"));
        this.helper.AddCheckListBoxItem(new CheckedPropertyItem("Property Three", "Property3"));
    }

    /// <summary>
    /// Handles the Click event of the Button1 control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void Button1_Click(object sender, EventArgs e)
    {
        // In the constructor
        // if we instantiated: this.helper = new CheckedListBoxPropertyHelper<MyItem>(this.checkedListBox1, this.myObjectDataSource, true);
        // as: this.helper = new CheckedListBoxPropertyHelper<MyItem>(this.checkedListBox1, this.myObjectDataSource, false);
        // changing the last bindImmediate property to false, the changes to the checkboxes wouldn't take effect immediately
        // on the underlying object, you need to call this.helper.CommitChanges() at which point the changes
        // will be made to the datasource object.

        // this.helper.CommitChanges();

        Console.WriteLine(this.myObjectDataSource.Property1.ToString());
        Console.WriteLine(this.myObjectDataSource.Property2.ToString());
        Console.WriteLine(this.myObjectDataSource.Property3.ToString());
    }
}

/// <summary>
/// My item.
/// </summary>
public class MyItem
{
    /// <summary>
    /// Gets or sets a value indicating whether this <see cref="MyItem"/> is property1.
    /// </summary>
    /// <value><c>true</c> if property1; otherwise, <c>false</c>.</value>
    public bool Property1
    {
        get;
        set;
    }

    /// <summary>
    /// Gets or sets a value indicating whether this <see cref="MyItem"/> is property2.
    /// </summary>
    /// <value><c>true</c> if property2; otherwise, <c>false</c>.</value>
    public bool Property2
    {
        get;
        set;
    }

    /// <summary>
    /// Gets or sets a value indicating whether this <see cref="MyItem"/> is property3.
    /// </summary>
    /// <value><c>true</c> if property3; otherwise, <c>false</c>.</value>
    public bool Property3
    {
        get;
        set;
    }
}

/// <summary>
/// The checked list box property helper. This binds datasource properties to checkedlistbox items.
/// </summary>
public class CheckedListBoxPropertyHelper<T> where T : class
{
    /// <summary>
    /// The checked list box.
    /// </summary>
    private CheckedListBox checkedListBox;

    /// <summary>
    /// The property info.
    /// </summary>
    private PropertyInfo[] PropertyInfo;

    /// <summary>
    /// Initializes a new instance of the <see cref="CheckedListBoxPropertyHelper"/> class.
    /// </summary>
    /// <param name="checkedListBox">The checked list box.</param>
    /// <param name="dataSource">The data source.</param>
    /// <param name="bindImmediate">if set to <c>true</c> [bind immediate].</param>
    public CheckedListBoxPropertyHelper(CheckedListBox checkedListBox, T dataSource, bool bindImmediate)
    {
        this.checkedListBox = checkedListBox;
        this.DataSource = dataSource;
        this.PropertyInfo = this.DataSource.GetType().GetProperties();
        this.BindImmediate = bindImmediate;
        this.checkedListBox.ItemCheck += new ItemCheckEventHandler(CheckedListBox_ItemCheck);
    }

    /// <summary>
    /// The data source.
    /// </summary>
    public T DataSource
    {
        get;
        private set;
    }

    /// <summary>
    /// Gets or sets a value indicating whether to [bind immediately] to the datasource object.
    /// </summary>
    /// <value><c>true</c> if [bind immediately]; otherwise, <c>false</c>.</value>
    public bool BindImmediate
    {
        get;
        set;
    }

    /// <summary>
    /// Commits the changes.
    /// </summary>
    public void CommitChanges()
    {
        if (!this.BindImmediate)
        {
            for (int i = 0; i < this.checkedListBox.Items.Count; i++)
            {
                CheckedPropertyItem checkedItem = this.checkedListBox.Items[i] as CheckedPropertyItem;
                this.SetChecked(this.checkedListBox.GetItemChecked(i), checkedItem);
            }
        }
        else
        {
            throw new InvalidOperationException("You cannot commit changes when bind immediate is on.");
        }
    }

    /// <summary>
    /// Adds the check list box item.
    /// </summary>
    /// <param name="item">The item.</param>
    public void AddCheckListBoxItem(CheckedPropertyItem item)
    {
        PropertyInfo info = this.GetPropertyInfo(item.PropertyName);
        bool isChecked = false;

        if (info != null)
        {
            isChecked = (bool)info.GetValue(this.DataSource, null);
        }

        this.checkedListBox.Items.Add(item, isChecked);
    }

    /// <summary>
    /// Handles the ItemCheck event of the CheckedListBox control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Windows.Forms.ItemCheckEventArgs"/> instance containing the event data.</param>
    private void CheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
    {
        if (BindImmediate)
        {
            CheckedListBox clb = sender as CheckedListBox;
            CheckedPropertyItem checkedItem = clb.Items[e.Index] as CheckedPropertyItem;

            this.SetChecked(
                e.NewValue == CheckState.Checked ? true : false,
                 checkedItem);
        }
    }

    /// <summary>
    /// Sets the checked.
    /// </summary>
    /// <param name="isChecked">if set to <c>true</c> [is checked].</param>
    /// <param name="clb">The CLB.</param>
    private void SetChecked(bool isChecked, CheckedPropertyItem item)
    {
        PropertyInfo info = this.GetPropertyInfo(item.PropertyName);

        if (info.CanWrite)
        {
            info.SetValue(this.DataSource, isChecked, null);
        }
    }

    /// <summary>
    /// Gets the property info.
    /// </summary>
    /// <param name="propertyName">Name of the property.</param>
    /// <returns></returns>
    private PropertyInfo GetPropertyInfo(string propertyName)
    {
        return this.PropertyInfo
            .Where(c => c.Name == propertyName)
            .SingleOrDefault();
    }
}

/// <summary>
/// Checked Property Item binding.
/// </summary>
public class CheckedPropertyItem
{
    /// <summary>
    /// Initializes a new instance of the <see cref="CheckedPropertyItem"/> class.
    /// </summary>
    /// <param name="title">The title.</param>
    /// <param name="propertyName">Name of the property.</param>
    public CheckedPropertyItem(string title, string propertyName)
    {
        this.Title = title;
        this.PropertyName = propertyName;
    }

    /// <summary>
    /// Gets or sets the title.
    /// </summary>
    /// <value>The title.</value>
    public string Title
    {
        get;
        private set;
    }

    /// <summary>
    /// Gets the name of the property.
    /// </summary>
    public string PropertyName
    {
        get;
        private set;
    }

    /// <summary>
    /// Returns a <see cref="System.String"/> that represents this instance.
    /// </summary>
    /// <returns>A <see cref="System.String"/> that represents this instance.</returns>
    public override string ToString()
    {
        return this.Title;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文