0

Background: I'm Using C#, WPF and Calburn.Micro to create a GUI-oriented application with a pre-defined set of polymorphic objects achieved by sub-classes inheriting from an abstract parent-class.

The user instantiates the different sub-classes using a form, which contains a combobox to select which class to instantiate (The Combobox SelectedItem is also planned to trigger changes the form contents according to the selected type's properties).

I've managed to bring all inheriting sub-classes into a BindableCollection by using:

    private void LoadSubClasses()
    {
        Type _parentClass = typeof(ParentClass);
        Assembly assembly = Assembly.GetExecutingAssembly();
        Type[] _types = assembly.GetTypes();

        IEnumerable<Type> SubClassesIEnumerable = _types.Where(t => t.IsSubclassOf(_parentClass));

        foreach (var _subclass in SubClassesIEnumberable)
        {
            SubClassesColletion.Add(_subclass);
        }
    }

    private BindableCollection<Type> _subClassesCollection = new BindableCollection<Type>();
    public BindableCollection<Type> SubClassesCollection
    {
        get { return _subClassesCollection; }
        set { _subClassesCollection = value; }
    }

In runtime I can see the Combobox populated by blank items (and the different collections in the debugger) which makes me thing that so far so good.

As I've stated before, some of the form contents will be changing according to the Combobox's SelectedItem, so I think the right direction is to have the Combobox item be the type, and then bind the different elements to the selected type's properties. I'm trying to implement that using ItemsTempalte, starting with the "subclass selector" Combobox displaying an abstract property (called "ViewName") which is overridden by all subclasses:

        <ComboBox x:Name="SubClassesCollection" Height="23" Margin="5,0,5,0">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <Label Content="{Binding Path=ViewName}"  Margin="-5"/>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>

But I fear this is as far as I can go, as looking up different solutions didn't get me anywhere.

D_mtsdt
  • 11
  • 3
  • 1
    Your actual question is not very clear, are you having problems with binding the list of items to the ComboBox (i.e. it's blank?), or binding the other elements of the form? – Charlie Drewitt Feb 10 '19 at 08:22
  • The Combobox is bound to the collection, but I can't seem to handle binding the Combobox items template to display properties from the list items. The part about the form elements is because I plan on binding form elements to the Combobox SelectedItem's properties which is why I felt it necessary to have the Combobox bound directly to a list of types, and not a helper class for example. – D_mtsdt Feb 10 '19 at 10:10
  • Update: Seems like my problem is in the databinding. When I change my XAML to simply: `` instead of `` I get the classes Display Names shown in the combobox. – D_mtsdt Feb 10 '19 at 11:49

1 Answers1

0

My issue is solved. I backtracked it to the LoadSubClasses method that populated the IEnumerable and changed it entirely for:

        public void LoadSubClasses()
    {
        IEnumerable<ParentClass> subClassesIEnumerable = typeof(ParentClass)
            .Assembly.GetTypes()
            .Where(t => t.IsSubclassOf(typeof(ParentClass)))
            .Select(t => (ParentClass)Activator.CreateInstance(t));

        foreach (ParentClass _subClass in subClassesIEnumerable)
        {
            _subClassesCollection.Add(_subClass);
        }
    }

    private BindableCollection<ParentClass> _subClassesCollection = new BindableCollection<ParentClass>();
    public BindableCollection<ParentClass> SubClassesCollection
    {
        get { return _subClassesCollection; }
        set { _subClassesCollection = value; NotifyOfPropertyChange(() => SubClassesCollection); }
    }

Correct me if I'm wrong but I believe my first attempt returned system.runtimetypes to the IEnumerable which were unworkable for me. The new LINQ code returns an instantiated object for each sub-class which can be put into a BindableCollection (instead of BindableCollection) and the databinding works fine.

Props to the guys who answered it here: Get all inherited classes of an abstract class

D_mtsdt
  • 11
  • 3