c# - 将枚举属性值绑定(bind)到 ListView.Items(WinForms)

标签 c# winforms data-binding enums

我有以下实体:

public class MyEntity
{
   public int Id {get;set}
   public Color SelectedColors 
}

MyEntityColor 枚举具有一对多关系。

[Flags]
public enum Color
{
   None=1,
   White=2,
   Red=3,
   Blue=4 
}

换句话说,每个 myEntity 对象可能有一个或多个来自 Color 枚举的值:

myEntity1.Color = Color.Red | Color.White;

我使用 Entity Framewrok 保存了这些数据:

using (var ctx = new MyContext())
{
   var entity1 = new MyEntity { SelectedColors = Color.Blue | Color.White };
   ctx.MyEntities.Add(entity1);
   ctx.SaveChanges();
}

并使用以下代码阅读它:

using (var ctx = new MyContext())
{
   var entity1 = ctx.MyEntities.Find(id); 
}

我想通过在chechboxes上打勾来显示选定的颜色,

我使用 ListView 控件(WinForms 项目)来完成这项工作:

listView1.CheckBoxes = true;
listView1.HeaderStyle = None;
listView1.View = List;

并使用以下代码将所有 Enum 值显示为 ListView.Items:

foreach (var value in Enum.GetValues(typeof(Color)).Cast<Color>())
{
   listView1.Items.Add(new ListViewItem() 
                           {
                             Name = value.ToString(),
                             Text = value.ToString(),
                             Tag = value
                           });
}

enter image description here

有没有办法将我的查询结果的 SelectedColors 值绑定(bind)到 listView1.Items

[更新]

我在 this link 中看到了解决方案那Nick-KListView 继承了一个新控件。我认为该解决方案对我不利,因为继承的控件采用 DataSourceDataMember,所以我应该为 DataMember 设置什么在我的例子中(SelectedColors 可能有多个值)?

最佳答案

如果您想编辑您的颜色,您可以为此从 ListView 继承您自己的控件:

public class ColorListControl : ListView
{
    public event EventHandler SelectedColorChanged;

    private Color selectedColor = Color.None;

    [DefaultValue( Color.None )]
    public Color SelectedColor
    {
        get { return selectedColor; }
        set
        {
            if( selectedColor != value )
            {
                selectedColor = value;

                foreach( ListViewItem item in this.Items )
                {
                    Color itemColor = (Color)item.Tag;
                    if( itemColor == Color.None ) //see http://stackoverflow.com/questions/15436616
                        item.Checked = value == Color.None;
                    else
                        item.Checked = value.HasFlag( itemColor );
                }

                SelectedColorChanged?.Invoke( this, EventArgs.Empty );
            }
        }
    }

    public ColorListControl()
    {
        this.CheckBoxes = true;
        this.HeaderStyle = ColumnHeaderStyle.None;
        this.View = View.List;

        foreach( Color value in Enum.GetValues( typeof( Color ) ).Cast<Color>() )
        {
            this.Items.Add( new ListViewItem()
            {
                Name = value.ToString(),
                Text = value.ToString(),
                Tag = value
            } );
        }
    }

    protected override void OnItemChecked( ItemCheckedEventArgs e )
    {
        base.OnItemChecked( e );

        Color checkedColor = (Color)e.Item.Tag;

        if( e.Item.Checked )
            SelectedColor |= checkedColor;
        else
            SelectedColor &= ~checkedColor;
    }
}

然后你可以绑定(bind)到它的属性 SelectedColor:

public class MainForm : Form
{
    private ColorListControl listView1;

    public MainForm()
    {
        InitializeComponent();

        MyEntity entity = new MyEntity { SelectedColors = Color.Blue | Color.White };

        listView1.DataBindings.Add( nameof( listView1.SelectedColor ), entity, nameof( entity.SelectedColors ) );
    }

    private void InitializeComponent()
    {
        this.listView1 = new ColorListControl();
        this.SuspendLayout();
        // 
        // listView1
        // 
        this.listView1.Location = new System.Drawing.Point(16, 16);
        this.listView1.Name = "listView1";
        this.listView1.Size = new System.Drawing.Size(200, 128);
        this.listView1.TabIndex = 0;
        this.listView1.SelectedColorChanged += new System.EventHandler(this.listView1_SelectedColorChanged);
        // 
        // MainForm
        // 
        this.ClientSize = new System.Drawing.Size(318, 189);
        this.Controls.Add(this.listView1);
        this.Name = "MainForm";
        this.Text = "Form";
        this.ResumeLayout(false);

    }

    private void listView1_SelectedColorChanged( object sender, EventArgs e )
    {
        this.Text = listView1.SelectedColor.ToString();
    }
}

正如@MSL 已经说过的:您需要以 2 的幂(0、1、2、4、8、16 ...)定义 Color 枚举的数字。参见 https://msdn.microsoft.com/library/system.flagsattribute.aspx

要编译此示例,您需要 C# 6.0/Visual Studio 2015。否则,您必须将 nameof( listView1.SelectedColor ) 替换为 "SelectedColor"

除了使用 ListView,您还可以考虑使用 CheckedListBox:

public class ColorListControl : CheckedListBox
{
    public event EventHandler SelectedColorChanged;

    private Color selectedColor = Color.None;

    [DefaultValue( Color.None )]
    public Color SelectedColor
    {
        get { return selectedColor; }
        set
        {
            if( selectedColor != value )
            {
                selectedColor = value;

                for( int i = 0; i < this.Items.Count; i++ )
                {
                    Color itemColor = (Color)this.Items[i];
                    if( itemColor == Color.None )
                        this.SetItemChecked( i, value == Color.None );
                    else
                        this.SetItemChecked( i, value.HasFlag( itemColor ) );
                }

                SelectedColorChanged?.Invoke( this, EventArgs.Empty );
            }
        }
    }

    public ColorListControl()
    {
        CheckOnClick = true;

        foreach( Color value in Enum.GetValues( typeof( Color ) ) )
            this.Items.Add( value );
    }

    protected override void OnItemCheck( ItemCheckEventArgs ice )
    {
        base.OnItemCheck( ice );

        Color checkedColor = (Color)this.Items[ice.Index];

        if( ice.NewValue == CheckState.Checked )
            SelectedColor |= checkedColor;
        else
            SelectedColor &= ~checkedColor;
    }
}

关于c# - 将枚举属性值绑定(bind)到 ListView.Items(WinForms),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39867136/

相关文章:

c# - 小数位的 XAML StringFormat 语法

c# - 将键/值匿名对象作为参数传递

C# 字符串连接和字符串驻留

c# - DataGridView:对所有选定的行应用编辑

c# - WinForms 按钮 : Autosize Maximumsize

c# - 将多个属性绑定(bind)到不同的来源

c# - 使用 C# 的正则表达式

c# - 在子窗体中单击按钮时如何刷新父窗体?

data-binding - 与 Windows Phone 8 的 map API 扩展绑定(bind)

javascript - 数据绑定(bind)的 secret 是什么?