I need to get a full collection of OxyPlot colors and bind them to a ComboBox of DataGrid for future selection. I managed to do it, but the names displayed in ComboBox are "0x00ff", "0x0001", etc. Unfortunately, I can only get an actual color name ("Green", "Blue", etc.) using the GetColorName() method.
The DisplayMemberPath works perfect with public properties, but when I tried to use a method, my "0x00ff" were replaced with empty strings.
Is there a way to use a method in DisplayMemberPath instead of a public property or is there an another way?
My C# code:
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Windows;
using OxyPlot;
namespace WpfTestApp
{
public partial class MainWindow : Window
{
public class Data
{
public OxyColor Color { set; get; } = OxyColors.Automatic;
}
public ObservableCollection<OxyColor> Colors { set; get; } = new ObservableCollection<OxyColor>(
typeof(OxyColors).GetFields(BindingFlags.Static | BindingFlags.Public).Where(f => f.FieldType == typeof(OxyColor)).
Select(f => f.GetValue(null)).Cast<OxyColor>().ToList());
public ObservableCollection<Data> ColorData { set; get; } = new ObservableCollection<Data>();
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
}
}
My XAML:
<Window.Resources>
<CollectionViewSource x:Key="ColorsItems" Source="{Binding Colors}" />
</Window.Resources>
<Grid>
<DataGrid x:Name="dataGrid" ItemsSource="{Binding ColorData}" AutoGenerateColumns="False" CanUserSortColumns="False" Margin="44,29,507,230">
<DataGrid.Columns>
<DataGridComboBoxColumn Header="OxyColors" ItemsSource="{Binding Source={StaticResource ColorsItems}}"
DisplayMemberPath="GetColorName"
SelectedValueBinding="{Binding Color}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
In WPF you cannot bind directly to methods.
Use a IValueConverter
:
OxyColorToColorNameConverter.cs
[ValueConversion(typeof(OxyColor), typeof(string))]
class OxyColorToColorNameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
=> value is IEnumerable<OxyColor> colors
? colors.Select(color => color.GetColorName())
: value is OxyColor color
? color.GetColorName()
: Binding.DoNothing;
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
=> value is IEnumerable<string> colorNames
? colorNames.Select(colorName => OxyColor.Parse(colorName))
: value is string colorName
? OxyColor.Parse(colorName)
: Binding.DoNothing;
}
MainWindow.xaml
<Window>
<Window.Reources>
<OxyColorToColorNameConverter x:Key="OxyColorToColorNameConverter" />
</Window.Resources>
<DataGrid ItemsSource="{Binding ColorData}">
<DataGrid.Columns>
<DataGridComboBoxColumn Header="OxyColors">
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource"
Value="{Binding RelativeSource={RelativeSource AncestorType=DataGrid},
Path=DataContext.Colors,
Converter={StaticResource OxyColorToColorNameConverter}}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource"
Value="{Binding RelativeSource={RelativeSource AncestorType=DataGrid},
Path=DataContext.Colors,
Converter={StaticResource OxyColorToColorNameConverter}}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
</DataGrid>
</Window>