2012-06-23 1 views
2

Я пишу небольшое приложение в C# (.NET 4.0). У меня есть datagridview, каждая строка представляет один объект. Мне нужен столбец combobox, который позволяет выбрать конкретное свойство этого объекта.Каждая строка (объект) с собственным источником привязки в datagridview?

Пример:

public class Car 
{ 
    public String Make {get; set;} 
    public BindingList<String> AllColors {get; set;} 
    public int SelectedColorIndex {get; set;} 
} 

Каждая строка представляет один объект автомобилей. Каждый (другой) автомобиль имеет собственный выбор возможных цветов (AllColors). Я хочу иметь столбец, в котором вы можете установить SelectedColorIndex, выбрав один из цветов из AllColors (AllColors относится к каждому объекту Car).

Примечание: Я составил этот пример, но он описывает, что я хочу выполнить.

Как это сделать? Единственное решение, которое я обнаружил, это иметь конкретное поле со списком вне datagridview, с помощью которого вы можете изменить выбранную строку. И в строке введите событие Я изменил источник данных источника bindings на текущий «AllColors».

Благодарим вас за ваше время и ответы.

+0

Итак, вы хотите, чтобы выпадающие списки для каждого автомобиля предлагали разные цвета? Являются ли цвета для каждого автомобиля подмножеством всех доступных цветов? –

+0

Да. У каждого автомобиля есть свои доступные цвета, и они не являются подмножеством множества «больших доступных цветов». (это просто пример в моем случае, каждый объект имеет собственный набор доступных свойств, которые снова являются объектами. Я сделал этот пример, чтобы сделать вещи более простыми). – Ben

+0

У меня будет пример, который, надеюсь, вскоре ответит на вопрос. Примерно через полпути через прототипирование. –

ответ

3

Вот код за рабочим примером, в котором доступные цвета отфильтровываются до цветов, указанных в списке AllColors связанного объекта.

Магия происходит в обработчиках событий CellBeginEdit и CellEndEdit - там мы предоставляем каждую ячейку со списком из связанной строки и затем сбрасываем ее при выходе.

Одна вещь, на которую опирается, имеет главный список, который содержит все цвета - нет никакого способа обойти это.

Также я добавил обработку для случая, когда новая строка требует значений по умолчанию. Все, что я делаю, - это установить выбранный индекс по умолчанию на один. Конечно, это не сработает в реальном мире, вам нужно что-то более умное! Событие DefaultValuedNeeded описывает here on MSDN.

public partial class Form1 : Form 
{ 

    private BindingSource cars; 
    private BindingSource masterColors; 

    public Form1() 
    { 
     InitializeComponent(); 

     masterColors = new BindingSource(); 
     masterColors.Add(new CarColor{Name = "Blue", Index = 1}); 
     masterColors.Add(new CarColor{Name = "Red", Index = 2}); 
     masterColors.Add(new CarColor { Name = "Green", Index = 3 }); 
     masterColors.Add(new CarColor { Name = "White", Index = 4 }); 

     BindingList<CarColor> fordColors = new BindingList<CarColor>(); 
     fordColors.Add(new CarColor{Name = "Blue", Index = 1}); 
     fordColors.Add(new CarColor{Name = "Red", Index = 2}); 

     BindingList<CarColor> toyotaColors = new BindingList<CarColor>(); 
     toyotaColors.Add(new CarColor { Name = "Green", Index = 3 }); 
     toyotaColors.Add(new CarColor { Name = "White", Index = 4 }); 

     cars = new BindingSource(); 
     cars.Add(new Car { Make = "Ford", SelectedColorIndex = 1, AllColors = fordColors }); 
     cars.Add(new Car { Make = "Toyota", SelectedColorIndex = 3, AllColors = toyotaColors }); 

     dataGridView1.DataSource = cars; 
     dataGridView1.Columns["SelectedColorIndex"].Visible = false; 
     //dataGridView1.Columns["AllColors"].Visible = false; 

     DataGridViewComboBoxColumn col = new DataGridViewComboBoxColumn(); 
     col.Name = "AvailableColors"; 
     col.DataSource = masterColors; 
     col.DisplayMember = "Name"; 
     col.DataPropertyName = "SelectedColorIndex"; 
     col.ValueMember = "Index"; 
     dataGridView1.Columns.Add(col); 

     dataGridView1.CellBeginEdit += new DataGridViewCellCancelEventHandler(dataGridView1_CellBeginEdit); 
     dataGridView1.CellEndEdit += new DataGridViewCellEventHandler(dataGridView1_CellEndEdit); 
     dataGridView1.DefaultValuesNeeded += new DataGridViewRowEventHandler(dataGridView1_DefaultValuesNeeded); 
    } 

    void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e) 
    { 
     if (e.ColumnIndex == dataGridView1.Columns["AvailableColors"].Index) 
     { 
      if (e.RowIndex != dataGridView1.NewRowIndex) 
      { 
       // Set the combobox cell datasource to the filtered BindingSource 
       DataGridViewComboBoxCell dgcb = (DataGridViewComboBoxCell)dataGridView1 
           [e.ColumnIndex, e.RowIndex]; 
       Car rowCar = dataGridView1.Rows[e.RowIndex].DataBoundItem as Car; 
       dgcb.DataSource = rowCar.AllColors; 
      } 

     } 
    } 

    private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) 
    { 
     if (e.ColumnIndex == dataGridView1.Columns["AvailableColors"].Index) 
     { 
      // Reset combobox cell to the unfiltered BindingSource 
      DataGridViewComboBoxCell dgcb = (DataGridViewComboBoxCell)dataGridView1 
          [e.ColumnIndex, e.RowIndex]; 
      dgcb.DataSource = masterColors; //unfiltered 
     } 
    } 

    void dataGridView1_DefaultValuesNeeded(object sender, DataGridViewRowEventArgs e) 
    { 
     e.Row.Cells["SelectedColorIndex"].Value = 1; 
    } 

} 

public class Car 
{ 
    public String Make { get; set; } 
    public BindingList<CarColor> AllColors { get; set; } 
    public int SelectedColorIndex { get; set; } 
} 

public class CarColor 
{ 
    public String Name { get; set; } 
    public int Index { get; set; } 
} 

я впервые узнал, как это сделать из DataGridView FAQ, большой ресурс, написанный Марком Rideout, руководителем программы в то время для DataGridView в Microsoft. Пример в фильтрах часто задаваемых вопросов, основанный на другом поле со списком, и использует DataTables, но принцип тот же.

+0

Большое спасибо, это решило мою проблему. – Ben