sara
sara

Reputation:

DataGridViewComboBoxColumn

I have two DataGridViewComboBoxColumn that I add at run time. I need the items of the first DataGridViewComboBoxColumn to stay the same in all the rows of the GridView but I want the items of the second DataGridViewComboBoxColumn to be different from row to another depending on the selected item of the first DataGridViewComboBoxColumn.

If we say the first DataGridViewComboBoxColumn represents the locations and the second DataGridViewComboBoxColumn represents the sublocations. So, I want the second DataGridViewComboBoxColumn items to be the sublocations of the selected location from the first DataGridViewComboBoxColumn.

Like this if Canada is selected

Country(comboBoxItems)  |     State/Province(ComboBox Items)
USA                           Quebec
CANADA(selected)              Ontario
ENGLAND                       Manitoba
                              Alberta

Then if you select USA

Country(comboBoxItems)  |     State/Province(ComboBox Items)
USA (Selected)                California
CANADA                        New York
ENGLAND                       Montana
                              Ohio

Upvotes: 0

Views: 616

Answers (1)

PapaAtHome
PapaAtHome

Reputation: 604

Recap of your problem:

You have a collection of data and want to filter on it.

This is a question with the same problem that extends on this subject a bit more. (To be specific, filter a LINQtoSQL IQueriable object before it is fired to the database.)

I found two solutions that might be interesting for our problem.

I found a way to do it for data in DataSets (ADO.NET)

DataTable source { get; set; }
String ValueMember { get; set; }
String DisplayMember { get; set; }
String FilterMember { get; set; }

Object ADOSelect(Object criterium)
{
    if ((source == null) || (criterium == null)) return null;

    return
    (
        from r in source.AsEnumerable()
        where (r[FilterMember] == criterium)
        select new
        {
            Value = r[ValueMember],
            Display = r[DisplayMember]
        }
    ).ToList();
}

And a more generic solution.

class Record
{
    public object Display { get; set; }
    public object Value { get; set; }
}

IEnumerable<Object> source { get; set; }
String ValueMember { get; set; }
String DisplayMember { get; set; }
String FilterMember { get; set; }

Object DataSelect(Object criterium)
{
    List<Record> result = new List<Record>();
    foreach (var record in source) Parse(sender, record, criterium, result);
    return result;
}

private void Parse(object record, Object criterium, List<Record> result)
{
    MethodInfo DisplayGetter = null;
    MethodInfo ValueGetter = null;
    bool AddRecord = false;

    foreach (PropertyInfo property in record.GetType().GetProperties())
    {
        if (property.Name == DisplayMember) DisplayGetter = property.GetGetMethod();
        else if (property.Name == ValueMember) ValueGetter = property.GetGetMethod();
        else if (property.Name == FilterMember)
        {
            MethodInfo ExternalGetter = property.GetGetMethod();
            if (ExternalGetter == null) break;
            else
            {
                object external = ExternalGetter.Invoke(record, new object[] { });
                AddRecord = external.Equals(criterium);
                if (!AddRecord) break;
            }
        }
        if (AddRecord && (DisplayGetter != null) && (ValueGetter != null)) break;
    }

    if (AddRecord && (DisplayGetter != null) && (ValueGetter != null))
    {
        Record r = new Record();
        r.Display = (DisplayGetter != null) 
            ? DisplayGetter.Invoke(record, new object[] { })
            : null;
        r.Value = (ValueGetter != null) 
            ? ValueGetter.Invoke(record, new object[] { })
            : null;
        result.Add(r);
    }
}

Upvotes: 1

Related Questions