问题
Using Live Charts 0.9.7 - and .NET 4.5
I'm trying to add a separator via code to an axis and bind the separator step value in code because I'm adding new series to a cartesian plot dynamically at runtime. The separator will change depending on how large the dataset is.
Here is my code:
public partial class PlottingTool : UserControl, INotifyPropertyChanged
{
public static SeriesCollection SeriesCollection { get; set; }
#region LineSeries1Specifics
private double _lineSeries1XAxisSeparatorStep;
// Separator for x-axis
public double LineSeries1XAxisSeparatorStep // Bind the separator for the x-axis to this.
{
get
{
return _lineSeries1XAxisSeparatorStep;
}
set
{
_lineSeries1XAxisSeparatorStep = value;
OnPropertyChanged("LineSeries1AxisSeparatorStep");
}
}
#endregion
public PlottingTool()
{
InitializeComponent();
// Setup Chart
SetupChart();
// DataContext for the liveChart
DataContext = this;
}
private void SetupChart()
{
// Create an empty series collection.
SeriesCollection = new SeriesCollection();
// Setup the axis for the first chart
ChartFile.AxisX.Add(new Axis
{
Title = "Time",
Unit = TimeSpan.FromSeconds(1).Seconds,
Separator = new LiveCharts.Wpf.Separator
{
IsEnabled = true
},
DisableAnimations = true
});
ChartFile.AxisY.Add(new Axis
{
Unit = 1,
DisableAnimations = true
});
// Bind the series1 separator to the x-axis for the first chart
Binding xAxisSeparatorBinding = new Binding();
xAxisSeparatorBinding.Source = this;
xAxisSeparatorBinding.Path = new PropertyPath("LineSeries1XAxisSeparatorStep");
xAxisSeparatorBinding.Mode = BindingMode.OneWay;
xAxisSeparatorBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(ChartFile.AxisX[0].Separator, LiveCharts.Wpf.Separator.StepProperty, xAxisSeparatorBinding);
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName">The property that has a new value.</param>
protected void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
#endregion
}
XAML Code:
<UserControl x:Class="DataAnalyzer.Controls.PlottingTool"
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:local="clr-namespace:DataAnalyzer.Controls"
xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<lvc:CartesianChart Name="ChartFile" Series="{Binding SeriesCollection}" Grid.Row="0" LegendLocation="Top" DisableAnimations="true" Hoverable="false" DataTooltip="{x:Null}" Margin="10">
</lvc:CartesianChart>
</Grid>
Adding the binding for the separator "step" causes the plot not to display and the UI to lock up, but nothing crashes and Visual Studio doesn't provide any feedback to what is causing the error. I'm wondering why this doesn't work -- because it seems like it should. I've set bindings for other items (like Title) using a similar method and it worked fine.
The binding is updating the value because I can track it's progress through the methods. It's the actual assignment of the binding that doesn't work.
Thanks...
回答1:
To prevent typos you could simply use the nameof
operator if you're using at least C#6 (.NET Framework 4.6 or above). That would look like this:
public double LineSeries1XAxisSeparatorStep
{
get
{
return _lineSeries1XAxisSeparatorStep;
}
set
{
_lineSeries1XAxisSeparatorStep = value;
OnPropertyChanged(nameof(LineSeries1XAxisSeparatorStep));
}
}
Or you can get even simpler if you modify your OnPropertyChanged
method:
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
You find CallerMemberName
in the System.Runtime.CompilerServices
namespace (since .NET Framework 4.5)
with this modification you could simplify your property to:
public double LineSeries1XAxisSeparatorStep
{
get { return _lineSeries1XAxisSeparatorStep; }
set { _lineSeries1XAxisSeparatorStep = value; OnPropertyChanged(); }
}
回答2:
So I figured out the issue -- simple typo in the following code (the property name passed was not correct - missing the X in LineSeries1XAxisSeparatorStep) for OnPropertyChanged (fixed below):
public double LineSeries1XAxisSeparatorStep // Bind the separator for the x-axis to this.
{
get
{
return _lineSeries1XAxisSeparatorStep;
}
set
{
_lineSeries1XAxisSeparatorStep = value;
OnPropertyChanged("LineSeries1XAxisSeparatorStep");
}
}
The program was hanging because I did not initialize the value for LineSeries1XAxisSeparatorStep, so the value it must have been using was 0 since it was not null. Initializing it not necessary if the binding is working correctly.
来源:https://stackoverflow.com/questions/50164439/wpf-live-charts-binding-separator-in-code-not-working