0

I´m working on a ComboBox derived class which could be able (under some circumstances) to add a "special" item to it DataSource source. The code is as follows

protected void InsertSpecial()
{
    // source is a List<T> protected field or property of the derived class
    object item = source[0]; 
    comboItemType = item.GetType();
    if (comboItemType == null || comboItemType.IsClass == false)
        return;
    whereProperty = comboItemType.GetProperty(comboBox1.DisplayMember,
                    BindingFlags.Public | BindingFlags.Instance);

    if (whereProperty == null)
        return;
    object special = Activator.CreateInstance(comboItemType);
    if (special == null)
        return;
    whereProperty.SetValue(special, "<special>", null);
    object result = Convert.ChangeType(special, comboItemType);
    MessageBox.Show(String.Format( "{0} {1}", result.GetType().ToString(), whereProperty.GetValue(result, null)) );
    // here, the compiler throw an error telling result is an invalid argument
    source.Insert(0, result);
}

All the code works ok in this agnostic mode, until the time to insert the new object in the list. Even after the Convert.ChangeType call (the MessgeBox shows the expected type). How can I cast the result object to the List<>´s expected type? TIA

marcelo
  • 215
  • 3
  • 13
  • itsme86 Could you point me to the duplicate? TIA – marcelo Jul 22 '18 at 18:49
  • itsme86 https://stackoverflow.com/questions/4010144/convert-variable-to-type-only-known-at-run-time is not the same. My code did a cast using Convert.ChangeType(). My problem was in the List.Add() method, where the compiler threw an error regarding the "type" of the object to add. Please, read carefully. – marcelo Jul 22 '18 at 21:10
  • @itsme86: It's not a dup. The problem is that the OP is trying to call `List.Insert(int index, T item)` with an object of type T, but using a reference typed as an `object`, and the compiler is objecting. I have a solution ready to post, but I don't have the juice to unmark the duplicate setting. If it doesn't get unmarked, here's the key 2 lines of code: `var addMethod = source.GetType().GetMethod("Insert"); addMethod.Invoke(source, new[] { 0, result});` The OP's use of `Convert.ChangeType` isn't needed at all here - the types are right; it's just that the compiler doesn't know that. – Flydog57 Jul 22 '18 at 22:07
  • Flydog57 Beforehand, thank you. I have also a solution, but cannot answer the OP. If source is an IList, you can Insert into it "anything". Even if the DataSource "provider" sends a List one could write `IList source = provider(); InsertSpecial(); combBox1.DataSouce = source;` – marcelo Jul 23 '18 at 11:27
  • By the way, you will have a hard time getting changes in your backing list to show up as changes in the combo box unless you use a BindingList (set the data source of the binding list to your list, then set the data source of the control to the binding list - reset the binding list's bindings when you change the list) – Flydog57 Jul 23 '18 at 18:36
  • Flydog57 You are right, but fortunately I need to Insert() a new instance only once, and this may well be before setting the combo DataSource, so I can go with Ilist. Nothing strange: if the underlying combo´s property is DbNullable, simply add a new item, with a DataMember set to some "special string" ("") that in turns, when SelectedItem is set to it, forces a SetValue( dest, null, null ) on the underlyng property. Of course, this addtion must be done only once. – marcelo Jul 24 '18 at 08:46
  • Flydog57 Nevertheless, I will take your tip into account if, in addition to the "null item" question, may be the underlying list could change at runtime. – marcelo Jul 24 '18 at 08:55

0 Answers0