Search code examples
wpfcolorsbindingoxyplot

LinieSeries Color Binding not work oxyPlot


I'm trying to bind the LineSeries Color to my viewmodel. It has no effect. What is wrong?

The Datacontext is set in the MainWindow. That works because I get the data from Chartpoints.

<UserControl x:Class="MyLayerThicknessApp.UserControls.RefAufnehmenEdit"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
             xmlns:local="clr-namespace:MyLayerThicknessApp.UserControls"
             mc:Ignorable="d" 
             d:DesignHeight="850" d:DesignWidth="1000">
    <Grid>
            <!--Chart-->
                <oxy:Plot 
                      LegendOrientation="Vertical"
                      LegendPlacement="Outside"
                      LegendPosition="RightTop" Grid.Row="1" IsEnabled="False">
                    <oxy:Plot.Axes>
                        <oxy:LinearAxis Position="Bottom" Minimum="400" Maximum="850"  MajorGridlineStyle="None" MinorGridlineStyle="None" Title="Wellenlänge [nm]" />
                <oxy:LinearAxis Position="Left" Minimum="0" Maximum="4000" Title="Intensität" MajorStep="1000" MajorGridlineStyle="Automatic" MinorGridlineStyle="None"/>
            </oxy:Plot.Axes>
                    <oxy:Plot.Series>
                        <oxy:LineSeries 

                                       DataFieldY="YValue" DataFieldX="XValue" ItemsSource="{Binding ChartPoints}" Color="{Binding LinieColor}" LineStyle="Solid" />
                    </oxy:Plot.Series>
                </oxy:Plot>

    </Grid>
</UserControl>

// Mainwindow
<Window x:Class="MyLayerThicknessApp.Views.RecipesView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MyLayerThicknessApp.Views"
        xmlns:vm="clr-namespace:MyLayerThicknessApp.ViewModels"
        xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
        xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"    
        xmlns:MyControls="clr-namespace:MyLayerThicknessApp.UserControls"
        mc:Ignorable="d"
        Title="RezepteWindow" Height="850" Width="1200" WindowStartupLocation="CenterOwner" Style="{StaticResource Window}" IsEnabled="{Binding MainWindowIsEnable}"  >
    <Window.DataContext>
        <vm:RecipesViewModel/>
    </Window.DataContext>


                <Grid Background="Transparent">
                    <MyControls:RefAufnehmenEdit Visibility="{Binding VisEditRefAufnehmen, Converter={StaticResource BooleanToVisibilityConverter}}"  />
                </Grid>

</Window>

My ViewModel. I also try with Color and Brushes. Nothing works. The INotifyPropertyChanged is in the MainViewMode. This works for sure.

public class RecipesViewModel : MainViewModel
{
    private bool visEditRefAufnehmen;
    public bool VisEditRefAufnehmen
    {
        get { return visEditRefAufnehmen; }
        set
        {
            if (visEditRefAufnehmen != value)
            {
                visEditRefAufnehmen = value;
                 OnPropertyChanged("VisEditRefAufnehmen");  // To notify when the property is changed
            }
        }
    }

    private OxyColor linieColor = OxyColor.Parse("255,0,0");
    public OxyColor LinieColor
    {
        get { return linieColor; }
        set
        {
            if (linieColor != value)
            {
                linieColor = value;
                OnPropertyChanged("LinieColor");  // To notify when the property is changed
            }
        }
    }

    private List<DataPoint> currentchartPoints;
    public List<DataPoint> CurrentchartPoints
    {
        get { return currentchartPoints; }
        set
        {
            if (value != currentchartPoints)
            {
                currentchartPoints = value;
                OnPropertyChanged("CurrentchartPoints");
            }
        }
    }

    private void spektrumAufnehmen()
    {
        if (spektrometer == null)
        {
            spektrometer = MySpektrometer.getInstanz();
            spektrometer.SetINtegrationTime(10);
        }

        Task.Run(() =>
        {
            while (VisEditRefAufnehmen)
            {
                double[] intensity = MySpektrometer.Wrapper.getSpectrum(0);
                double[] wave = MySpektrometer.Wrapper.getWavelengths(0);

                wave = MyFilter.convertBigArrayToSmall(wave, intensity, Brechungsindex.WAVELENGTHAREA);
                ChartPoints = DoubleArrayToChartPoints(wave);
            }
        });

    }
}
// INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}

Solution

  • The property LineSeries.Color expects a type of System.Windows.Media.Color, where as, the the property in your ViewModel, LinieColor, is of type OxyColor.

    From OxyPlot Source

    public static readonly DependencyProperty ColorProperty = DependencyProperty.Register(
                    "Color", typeof(Color), typeof(Series), new PropertyMetadata(MoreColors.Automatic, AppearanceChanged));
    

    From your ViewModel

    public OxyColor LinieColor
    

    You could resolve the binding issue by using a converter that converts OxyColor to Color. A simplest converter for the purpose could be following.

    public class OxyColorToColorConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if (value is OxyColor color)
                    return color.ToColor();
    
                return value;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    

    And in your XAML

    <oxy:LineSeries DataFieldY="YValue" DataFieldX="XValue" ItemsSource="{Binding ChartPoints}" Color="{Binding LinieColor,Converter={StaticResource OxyColorToColorConverter}}" LineStyle="Solid" />