Checkable legend
luckymichael wrote at 2012-08-20 20:03:
is it possible to add checkbox in front of the legend items to change the IsVisible property?
Thanks
objo wrote at 2012-08-21 12:59:
Sorry, this is currently not possible. (this will require checkbox and binding functionality in the IRenderingContext)
I think this should be solved by the client application - if you use WPF/SL it should be possible to overlay the legend box over the plot control, and bind the checkboxes to the PlotModel.
pdinnissen wrote at 2012-12-07 18:17:
Hi luckymichael,
Have you had any luck performing this?
Thanks,
Pierre
wolf9s wrote at 2014-07-26 05:03:
Sorry, this is currently not possible. (this will require checkbox and binding functionality in the IRenderingContext) I think this should be solved by the client application - if you use WPF/SL it should be possible to overlay the legend box over the plot control, and bind the checkboxes to the PlotModel.First, I use WPF:
How solved the problem in the client application ?
How overlay ?
How bind checkboxes to the PlotModel?
Slxe wrote at 2014-07-27 05:45:
wolf9s wrote at 2014-07-28 04:52:
Yes , I need you more help, need sample code.
Slxe wrote at 2014-07-28 18:06:
DJDAS wrote at 2014-08-07 12:28:
I found a solution that matched quite well my needs some time ago, following there is a simplified extract of my XAML code; essentially there is a graph and a stack panel with the checkboxes used as legend, all the "magic" is done by XAML binding, unfortunately I was not able to customize the bindings to the checkbox name to avoid repeating the code in the style of each series so I had to copy/paste the Style Triggers (I have about 25 series for one graph and 10 for another graph in the same page).
The properties bound to get data are List<DataPoint> for the Line and StairStep Series, while I created a new struct "AreaDataPoint" which is basically an extension of the DataPoint one with a "Y2" property to have the second values for the Y axys so in that case I have a List<AreaDataPoint> for the AreaSeries source items.
In the example you can also find a trick I used to hide all the AreaSeries with just one checkbox giving them different style colors, hope it will be useful :)
Disclaimer: I copied/pasted pieces of my code renaming all the styles, properties and so on because of NDA agreements so I'm not sure this code compiles, please use it as a sample idea not as a working solution (i.e. plot and axes styles are not included because they're simply dimensions and colors).
<Style x:Key="cbSeriesCheckboxes" TargetType="{x:Type CheckBox}" > <Setter Property="MinHeight" Value="16" /> <Setter Property="IsEnabled" Value="True" /> </Style> <Style x:Key="AreaSeriesSampleStyle" TargetType="{x:Type oxy:AreaSeries}"> <Setter Property="LineStyle" Value="Solid" /> <Setter Property="StrokeThickness" Value="1" /> <Setter Property="DataFieldY2" Value="Y2" /> <Setter Property="DataFieldX2" Value="X" /> <Setter Property="Visibility" Value="Collapsed" /> <Setter Property="Title" Value="{Binding ElementName=cbAreaSeriesSample, Path=Content}" /> <Style.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding ElementName=cbAreaSeriesSample, Path=IsChecked}" Value="True"/> <Condition Binding="{Binding ElementName=cbAreaSeriesSample, Path=IsVisible}" Value="True"/> </MultiDataTrigger.Conditions> <Setter Property="Visibility" Value="Visible" /> </MultiDataTrigger> </Style.Triggers> <Style.Triggers> <Trigger Property="Tag" Value="0"> <Setter Property="Fill" Value="#4490EE90" /> <Setter Property="Color" Value="LightGreen" /> </Trigger> <Trigger Property="Tag" Value="1"> <Setter Property="Fill" Value="#44FFD700" /> <Setter Property="Color" Value="Gold" /> </Trigger> <Trigger Property="Tag" Value="2"> <Setter Property="Fill" Value="#44FFA500" /> <Setter Property="Color" Value="Orange" /> </Trigger> <Trigger Property="Tag" Value="3"> <Setter Property="Fill" Value="#445F9EA0" /> <Setter Property="Color" Value="CadetBlue" /> </Trigger> </Style.Triggers> </Style> <Style x:Key="cbAreaSeriesSample" TargetType="{x:Type CheckBox}" BasedOn="{StaticResource cbSeriesCheckboxes}"> <Setter Property="Foreground" Value="Green" /> <Setter Property="Background" Value="WhiteSmoke" /> </Style> <Style x:Key="StepSeriesSampleStyle" TargetType="{x:Type my:StairStepSeries}"> <Setter Property="Color" Value="Blue" /> <Setter Property="Title" Value="{Binding ElementName=cbStepSeriesSample, Path=Content}" /> <Style.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding ElementName=cbStepSeriesSample, Path=IsChecked}" Value="True"/> <Condition Binding="{Binding ElementName=cbStepSeriesSample, Path=IsVisible}" Value="True"/> </MultiDataTrigger.Conditions> <Setter Property="Visibility" Value="Visible" /> </MultiDataTrigger> </Style.Triggers> </Style> <Style x:Key="cbStepSeriesSample" TargetType="{x:Type CheckBox}" BasedOn="{StaticResource cbSeriesCheckboxes}"> <Setter Property="Foreground" Value="Blue" /> <Setter Property="Background" Value="WhiteSmoke" /> </Style> <Style x:Key="LineSeriesSampleStyle" TargetType="{x:Type oxy:LineSeries}" > <Setter Property="LineStyle" Value="Solid" /> <Setter Property="StrokeThickness" Value="3" /> <Setter Property="Visibility" Value="Collapsed" /> <Setter Property="CanTrackerInterpolatePoints" Value="False" /> <Setter Property="Color" Value="Brown" /> <Setter Property="Title" Value="{Binding ElementName=cbLineSeriesSample, Path=Content}" /> <Style.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding ElementName=cbLineSeriesSample, Path=IsChecked}" Value="True"/> <Condition Binding="{Binding ElementName=cbLineSeriesSample, Path=IsVisible}" Value="True"/> </MultiDataTrigger.Conditions> <Setter Property="Visibility" Value="Visible" /> </MultiDataTrigger> </Style.Triggers> </Style> <Style x:Key="cbLineSeriesSample" TargetType="{x:Type CheckBox}" BasedOn="{StaticResource cbSeriesCheckboxes}"> <Setter Property="Foreground" Value="Brown" /> <Setter Property="Background" Value="WhiteSmoke" /> </Style> <StackPanel x:Name="Graphs" Orientation="Vertical"> <oxy:Plot x:Name="TopPlot" Style="{StaticResource Plot}" MinHeight="380" Height="400" > <oxy:Plot.Axes> <oxy:DateTimeAxis Style="{StaticResource DateTimeAxis}"/> <oxy:LinearAxis Style="{StaticResource LinearAxis}"/> </oxy:Plot.Axes> <oxy:AreaSeries Style="{StaticResource AreaSeriesSampleStyle}" ItemsSource="{Binding AreaSeriesData0}" Tag="0"/> <oxy:AreaSeries Style="{StaticResource AreaSeriesSampleStyle}" ItemsSource="{Binding AreaSeriesData1}" Tag="1"/> <oxy:AreaSeries Style="{StaticResource AreaSeriesSampleStyle}" ItemsSource="{Binding AreaSeriesData2}" Tag="2"/> <oxy:AreaSeries Style="{StaticResource AreaSeriesSampleStyle}" ItemsSource="{Binding AreaSeriesData3}" Tag="3"/> <my:StairStepSeries Style="{StaticResource StepSeriesSampleStyle}" ItemsSource="{Binding StepSeriesSampleData}"/> <oxy:LineSeries Style="{StaticResource LineSeriesSampleStyle}" ItemsSource="{Binding LineSeriesSampleData}"/> </oxy:Plot> </StackPanel> <StackPanel> <CheckBox x:Name="cbAreaSeriesSample" Style="{StaticResource cbAreaSeriesSample}" Content="Area Series" /> <CheckBox x:Name="cbStepSeriesSample" Style="{StaticResource cbStepSeriesSample}" Content="StairStep Series" IsChecked="True"/> <CheckBox x:Name="cbLineSeriesSample" Style="{StaticResource cbLineSeriesSample}" Content="Line Series" IsChecked="False" /> </StackPanel>
Slxe wrote at 2014-08-07 15:31:
DJDAS wrote at 2014-08-07 15:36:
Many thanks!
Bye!
Slxe wrote at 2014-08-07 17:22:
/// <summary> /// Refreshes the custom legend based on the axes and series in the PlotModel. /// </summary> private void UpdateCustomLegend() { uiSeriesLegendLayout.Controls.Clear(); uiAxesLegendLayout.Controls.Clear(); foreach (LineSeries s in PlotModel.Series.OfType<LineSeries>().OrderBy(s => s.Title)) { var seriesColorButton = new Button { AutoSize = true, BackColor = s.Color.ToColor(), FlatStyle = FlatStyle.Flat, Size = new Size(30, 15), Tag = s.Tag, UseVisualStyleBackColor = false }; seriesColorButton.Click += (sender, args) => { using (var d = new ColorDialog()) { d.Color = s.Color.ToColor(); if (d.ShowDialog() != DialogResult.OK) return; s.Color = d.Color.ToOxyColor(); ((Button) sender).BackColor = d.Color; PlotModel.InvalidatePlot(false); } }; var seriesVisibilityCheckBox = new CheckBox { AutoSize = true, Checked = s.IsVisible, Tag = s.Tag, Text = s.Title }; seriesVisibilityCheckBox.CheckedChanged += (sender, args) => { s.IsVisible = ((CheckBox) sender).Checked; PlotModel.InvalidatePlot(false); }; uiSeriesLegendLayout.Controls.Add(seriesColorButton); uiSeriesLegendLayout.Controls.Add(seriesVisibilityCheckBox); uiSeriesLegendLayout.SetFlowBreak(seriesVisibilityCheckBox, true); } var seriesSelectAllCheckBox = new CheckBox { AutoSize = true, Checked = true, Text = "Select All" }; seriesSelectAllCheckBox.CheckedChanged += (sender, args) => { foreach (CheckBox cb in uiSeriesLegendLayout.Controls.OfType<CheckBox>()) cb.Checked = ((CheckBox) sender).Checked; }; uiSeriesLegendLayout.Controls.Add(seriesSelectAllCheckBox); var hideLinkedSeriesCheckBox = new CheckBox { AutoSize = true, Checked = false, Text = "Hide Linked Series" }; foreach (LinearAxis a in PlotModel.Axes.OfType<LinearAxis>()) { var axisVisibilityCheckBox = new CheckBox { AutoSize = true, Checked = a.IsAxisVisible, Tag = a.Tag, Text = a.Title }; axisVisibilityCheckBox.CheckedChanged += (sender, args) => { a.IsAxisVisible = ((CheckBox) sender).Checked; PlotModel.InvalidatePlot(false); if (!hideLinkedSeriesCheckBox.Checked) return; foreach ( LineSeries s in PlotModel.Series.OfType<LineSeries>() .Where(s => s.YAxisKey == a.Key || s.XAxisKey == a.Key)) { s.IsVisible = a.IsAxisVisible; uiSeriesLegendLayout.Controls.OfType<CheckBox>() .Single(cb => cb.Tag == s.Tag) .Checked = s.IsVisible; } }; uiAxesLegendLayout.Controls.Add(axisVisibilityCheckBox); uiAxesLegendLayout.SetFlowBreak(axisVisibilityCheckBox, true); } var axisSelectAllCheckBox = new CheckBox { AutoSize = true, Checked = true, Text = "Select All" }; axisSelectAllCheckBox.CheckedChanged += (sender, args) => { foreach ( CheckBox cb in uiAxesLegendLayout.Controls.OfType<CheckBox>() .Where(cb => cb != hideLinkedSeriesCheckBox)) cb.Checked = ((CheckBox) sender).Checked; }; uiAxesLegendLayout.Controls.Add(axisSelectAllCheckBox); uiAxesLegendLayout.Controls.Add(hideLinkedSeriesCheckBox); }
Customer support service by UserEcho
Let me know what you think please =) any feedback is always helpful!