3

I have an ObservableCollection of Base Objects bound to a datagrid. I am trying to populate a DataGridComboBoxColumn with Enum values from a derived class instantiated in the observable collection.

  1. How do I bind an enum from a derived class to a comboboxcolumn?
  2. How do ensure that the combobox values are bound to the unique enum in the derived instance as I have multiple derived classes that can be instantiated?

Things I've tried

  1. Create a public list in the base class (CmdsList) and populate it with the enum values from the derived class and bind it that way. but that hasn't worked
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.Base.CmdsList}"
  1. Create a data object within Window.Resources and bind as a static resource, but I am unsure of how to make this work with derived classes.

MainWindow

public partial class MainWindow : Window
{
    public ObservableCollection<Base> Collection{ get; set; }
    public MainWindow()
    {
        InitializeComponent();
        Collection = new ObservableCollection<Base>();
        this.DataContext = this;
    }
}

Base Class

public abstract class Base: INotifyPropertyChanged
{
    public abstract event EventHandler<DataEventArgs> dataUpdate;
    public string? addr;
    public string? name {get; set;}
    public string? port {get; set;}
}

Derived Class 1

public class Derived : Base
{
    public override event EventHandler<DataEventArgs>? dataUpdate;
    public enum CMDS
    {
        CMD1 = 0x024F032E,
        CMD2 = 0x0253032A,
        CMD3 = 0x0252032B,
        CMD4 = 0x0250032D,
        CMD5 = 0x0270030D,
        CMD6 = 0x02570326
    }
}

Derived Class 2

public class Derived2 : Base
{
    public override event EventHandler<DataEventArgs>? dataUpdate;
    public enum CMDS
    {
        CMD1 = 0x024F332E,
        CMD2 = 0x0224F32A,
        CMD3 = 0x0252032B,

    }
}

XAML

<DataGrid ItemsSource="{Binding Collection}" AutoGenerateColumns="False" CanUserAddRows="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Binding="{Binding name}"></DataGridTextColumn>
        <DataGridComboBoxColumn Header="Protocol"></DataGridComboBoxColumn>
        <DataGridTextColumn Header="IP Address"></DataGridTextColumn>
        <DataGridTextColumn Header="Port" Binding="{Binding port}"></DataGridTextColumn>
        <DataGridComboBoxColumn></DataGridComboBoxColumn>
</DataGrid>
1
  • I don't think this is considered a "good" use of an enum ... since it is basically an "open collection" of commands. I think a "List" (of command enum values) or Dictionary (with extra "command information") would be more practical (when "attached" to a class). Commented Aug 1 at 1:15

1 Answer 1

2

You should be able to use a ValueConverter for this:

public class EnumBindingConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value?.GetType() switch
        {
            Type t when t == typeof(Derived)  => Enum.GetValues(typeof(Derived.CMDS)),
            Type t when t == typeof(Derived2) => Enum.GetValues(typeof(Derived2.CMDS)),
            _ => null
        };
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        => throw new NotImplementedException();
}
<DataGridComboBoxColumn ItemsSource="{Binding Converter={StaticResource EnumBindingConverter}}"/>

Sign up to request clarification or add additional context in comments.

5 Comments

Assuming the nested enum type is always named CMDS, the Convert method could simply return Enum.GetValues(value.GetType().GetNestedType("CMDS"));
@Andrew KeepCoding I added the EnumConverter to my resources <local:EnumConverter x:Key="EnumBindingConverter"/> and bound the CMDS to the ComboBox as such: "{Binding CMDS, Converter={StaticResource EnumBindingConverter}}" I am still unable to populate the Combobox. Is binding the CMDS enum directly as I did incorrect or is there something else I am missing?
@Clemens Yes, the nested enum type will always be named CMDS.
@Clemens I am not understanding how to pass the derived CMDS enum to converter in this line ItemsSource="{Binding Converter={StaticResource EnumBindingConverter}}". Don't I need to bind the property to ComboBox?
There is no property to bind to. Not sure if you want to add a property of type CMDS to each derived type, and what you are going to do with it. To only populate the ComboBox, that ItemsSource Binding should be sufficient with the converter shown in this answer. You do not need to "pass the derived CMDS" because that is what the converter does.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.