2016-10-05 116 views
2

我具有以下實體:綁定枚舉屬性值ListView.Items(的WinForms)

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

MyEntity具有Color枚舉One-to-Many關係。

[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; 

,並使用下面的代碼來顯示所有EnumListView.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值綁定到listView1.Items

[更新]

我看到了一個解決方案,那this link繼承Nick-K新的控制從ListView。我認爲這種解決方案對我來說並不好,因爲繼承的控件採用DataSourceDataMember,那麼我應該怎樣設置DataMember(我的情況是SelectedColors可能有多個值)?

+0

的可能的複製[是否有可能一個列表綁定到的WinForms一個ListView?(http://stackoverflow.com/questions/2799017/is-it-possible-to-bind-a -list到一個-列表視圖-IN- winforms) – MSL

+0

爲了使用數據綁定,您需要一個控件和一個具有相同類型屬性的實體,在您的案例'Color'中。看起來你沒有別的選擇,只能從'ListView'(或'CheckedListBox')繼承自定義控件。 然後你的'DataSource'是實體,'DataMember'是'SelectedColors'。不要擔心列表事物,因爲[Flags] enum'實際上不是一個列表,即使它可以有多個值。試着想象它就像一個整數,你可以按給定的名字單獨設置和取消設置每一位。 例如無:0000,白色:0001,白色| Blue:0101 –

回答

0

如果你想編輯你的顏色,你可以從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; 
    } 
} 

事後你可以綁定到其屬性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已經說過:你需要用兩個冪(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; 
    } 
} 
+0

謝謝,你的解決方案:)。你說我也可以使用'CheckedListBox',但是我不能將'SelectionMode'設置爲Multi。你有其他解決方案嗎? – Masoud

+0

更正,對於CheckedListBox對象,不支持多選。但這並不重要,因爲它只決定可以選擇多少項目(用藍色背景標記)。但是你可以檢查(勾選複選框)儘可能多的項目。 我已經編輯了我的答案,以顯示如何使用CheckedListBox執行此操作。 –

+0

它可以工作,但是當我多次運行程序時,'ColorListControl'包含多組顏色,另一個詞'ColorListControl'包含'None,Red,Green,Blue,None,Red,Green,Blue ... '。 (也在設計時間和運行時間),你知道問題在哪裏嗎? – Masoud

0

的ListView類不支持的設計時間,在此

http://www.codeproject.com/Articles/10008/Data-binding-a-ListView

首先你枚舉的結合

看應該是這樣的:

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

使用此屬性

public List<string> SelectedColorsList 
{ 
    get 
    { 
     return SelectedColors.ToString() 
       .Split(new[] { ", " }, StringSplitOptions.None) 
       .ToList(); 
    } 
    set 
    { 
     if (value == null) 
     { 
      this.SelectedColors = MyColors.None; 
      return; 
     } 

     int s = 0; 
     foreach (var v in value) 
     { 
      s += (int)Enum.Parse(typeof(MyColors), v); 
     } 

     this.SelectedColors = (MyColors)s; 
    } 
} 
+0

那麼,我的情況是什麼'DataMember'? 'SelectedColors'可能有多個值。 – Masoud

+0

創建一個類型列表的新屬性,並將您的枚舉轉換爲列表,並將其轉換爲enum列表。然後將此屬性綁定到數據庫 – MSL

+0

1-How to convert'SelectedColors' value to list?你可以用代碼顯示我嗎? 2-我想檢查ListView中「SelectedColors」值的複選框。 – Masoud

0

如果你只想視圖的顏色,你可以設置的ListViewItemChecked - 屬性沒有任何數據綁定或自定義控制:

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

我想查看並保存顏色。 – Masoud

+0

在這種情況下,請參閱我的其他答案;-) –