ComboBox On DataRepeater Control Shares Selected I

2019-02-19 01:33发布

问题:

I have a data repeater with each row using a combobox. When you click the Add button it adds a new row to the DataRepeater.

   public enum ColorTypes {Red, Green, Yellow}
   class LineItem
   {
       public ColorTypes Color {get;set;} 
   }

When you click a button on the form it then creates a new LineItem, and rebinds.

  private void btnAdd_Click(object sender, EventArgs e)
  {
       LineItem CopyItem = new LineItem();
       CurrentList= ((List<LineItem>)dataRepeater.DataSource); 

       CurrentList.Add(CopyItem);
       dataRepeater.DataSource = CurrentList;
  }

This correctly adds a new row to the DataRepeater, but now changing combobox's index modifies both rows. Is there some special binding you need to perform?

Heres my binding code:

 this.cbPackage.DataSource = System.Enum.GetValues(typeof(ColorTypes));
 this.cbPackage.DisplayMember = "Color";

回答1:

After a LOT of searching and putting things together, you CAN pull this off! In order to properly use a combo box in a DataRepeater you will need to add the following events.

this.dataForm.ItemCloned += new Microsoft.VisualBasic.PowerPacks.DataRepeaterItemEventHandler(dataForm_ItemCloned);
this.dataForm.DrawItem += new Microsoft.VisualBasic.PowerPacks.DataRepeaterItemEventHandler(dataForm_DrawItem);
this.cbPackage.SelectedIndexChanged += new System.EventHandler(cbColor_SelectedIndexChanged);

MSDN ItemCloned

MSDN DrawItem

Now when the ItemCloned event is called you need to find your combo box control and manual map the data source (this prevents the dropdowns from using the same source and share the same selected index)

    void dataForm_ItemCloned(object sender,                Microsoft.VisualBasic.PowerPacks.DataRepeaterItemEventArgs e)
    {
        var combo = (ComboBox)e.DataRepeaterItem.Controls.Find("cbColor", false)[0];
        //Set the data source
        Combo.DataSource = System.Enum.GetValues(typeof(DataRepeater.ColorTypes));
    }

If your data changes on an add row, or you need to redraw the repeater the combo box index will be set to null. So to fix it, after the item template is done you're going to have to reset the selected index on draw.

    /// <summary>
    /// After Item is cloned, draw item. The index is now available to select the proper data
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void dataForm_DrawItem(object sender, Microsoft.VisualBasic.PowerPacks.DataRepeaterItemEventArgs e)
    {
        var dataRepeater = (Microsoft.VisualBasic.PowerPacks.DataRepeater)sender;
        var combo = (ComboBox)e.DataRepeaterItem.Controls.Find("cbPackage", false)[0];
        //Set the selected item based of the list item index
        Combo.SelectedItem = ((List<LineItem>)DataRepeater.DataSource)[e.DataRepeaterItem.ItemIndex].PackageType;  
    }

Finally, the last issue occurs when you change the value of the dropdown. The datasource does not get updated automatically. So now you need to manually update the source based of the index of the combobox.

 void cbPackage_SelectedIndexChanged(object sender, System.EventArgs e)
    {
        var combo = (ComboBox)sender;
        var dataRepeaterItem = (Microsoft.VisualBasic.PowerPacks.DataRepeaterItem)combo.Parent;
        var dataRepeater = (Microsoft.VisualBasic.PowerPacks.DataRepeater)combo.Parent.Parent;
        var source = ((List<ColorData>)DataRepeater.DataSource)[DataRepeaterItem.ItemIndex];
        source.PackageType = (DropData)combo.SelectedValue;        
    }

Wow... There you go, everything should be all set.