C# WPF 实时图表 - 创建通用图表

标签 c# wpf

我正在使用 WPF 实时图表库。我正在尝试创建一个通用的条形图。

以下是我的代码。无法在 XAML 中执行此操作,因为它不支持泛型。

public abstract class AbstractGenericBarChart<T> : UserControl, INotifyPropertyChanged
{
    SeriesCollection _SeriesCollection;
    public SeriesCollection SeriesCollection { get { return _SeriesCollection; } set { _SeriesCollection = value; notifyPropertyChanged("SeriesCollection"); } }
    string[] _Labels;
    public string[] Labels { get { return _Labels; } set { _Labels = value; notifyPropertyChanged("Labels"); } }
    Func<int, string> _Formatter;
    public Func<int, string> Formatter { get { return _Formatter; } set { _Formatter = value; notifyPropertyChanged("Formatter"); } }

    public abstract void constructChart(List<T> chartItems);

    public void init(string xLabel, string yLabel)
    {
        renderChart(xLabel, yLabel);
    }

    public void renderChart(string xLabel, string yLabel)
    {
        CartesianChart chart = new CartesianChart { Margin = new Thickness(10, 10, 10, 10), LegendLocation = LegendLocation.Bottom, DataTooltip = new DefaultTooltip { SelectionMode = TooltipSelectionMode.SharedYValues } };
        Axis xAxis = new Axis { Foreground = Brushes.Black, FontSize = 14d, Title = xLabel };
        Axis yAxis = new Axis { Foreground = Brushes.Black, FontSize = 14d, Title = yLabel };
        chart.AxisX.Add(xAxis);
        chart.AxisY.Add(yAxis);
        setBinding("LabelFormatter", Formatter, xAxis, Axis.LabelFormatterProperty);
        setBinding("Labels", Labels, yAxis, Axis.LabelsProperty);
        setBinding("Series", SeriesCollection, chart, CartesianChart.SeriesProperty);
        Content = chart;
    }

    public void setBinding(string propertyName, object source, FrameworkElement control, DependencyProperty dependencyProperty)
    {
        Binding binding = new Binding(propertyName)
        {
            Source = source
        };
        control.SetBinding(dependencyProperty, binding);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void notifyPropertyChanged(string prop)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
    }
}


internal class BarChart : AbstractGenericBarChart<TopTransactingCount>
{
    public override void constructChart(List<TopTransactingCount> chartItems)
    {
        SeriesCollection = new SeriesCollection
        {
            new RowSeries
            {
                Title = "Transaction Count",
                Values = new ChartValues<long>(chartItems.Select(x=>x.TransCount))
            }
        };
        Labels = chartItems.Select(x => x.Date.ToShortDateString()).ToArray();
        Formatter = value => value.ToString();
        DataContext = this;
    }
}

启动时我看到一个空的图表控件,这是预期的。

我在单击提交按钮时调用constructChart方法。

public partial class TotalTransCountsChart : UserControl, IChart
{
    private BarChart chart = new BarChart();
    List<object> chartData;

    public TotalTransCountsChart()
    {
        InitializeComponent();
    }

    public void init(List<object> chartData)
    {
        this.chartData = chartData;
        chart.init("Transaction Count", "Date");
        chart.constructChart(chartData.Cast<TopTransactingCount>().ToList());
        grid.Children.Add(chart);
        Grid.SetRow(chart, 3);
    }

    private void CmdSubmit_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        chart.constructChart(chartData.Cast<TopTransactingCount>().ToList());
    }
}

但是,图表仍然是空的。我认为代码中的绑定(bind)部分未按预期工作。我被困在这一点上。

最佳答案

看起来您创建的绑定(bind)不正确(尝试从 Visual Studio 输出窗口确认 - 它报告有关不正确绑定(bind)的消息)。

例如:

setBinding("Labels", Labels, yAxis, Axis.LabelsProperty);

public void setBinding(string propertyName, object source, FrameworkElement control, DependencyProperty dependencyProperty)
{
    Binding binding = new Binding(propertyName)
    {
        Source = source
    };
    control.SetBinding(dependencyProperty, binding);
}

Labels 是一个 string[],并且您有一个绑定(bind),它尝试使用“Labels”属性 - 该属性不存在。

您需要一个有效的绑定(bind)源,很可能是 DataContext:

setBinding("LabelFormatter", DataContext, xAxis, Axis.LabelFormatterProperty);
setBinding("Labels", DataContext, yAxis, Axis.LabelsProperty);
setBinding("Series", DataContext, chart, CartesianChart.SeriesProperty);

或者更好 - 不指定源,所有绑定(bind)都将连接到当前的 DataContext,即使它更新:

public void setBinding(string propertyName, object source, FrameworkElement control, DependencyProperty dependencyProperty)
{
    Binding binding = new Binding(propertyName);
    control.SetBinding(dependencyProperty, binding);
}

关于C# WPF 实时图表 - 创建通用图表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58876562/

相关文章:

c# - 如何在 C# 中找到我的线程在其上运行的处理器?

c# - 如何防止其他应用程序窃取焦点?

wpf - 将 DataTemplate 用于基础设施 XamComboEditor (WPF)

wpf - 删除WPF ListView的“经典”缩进边框

c# - 无法在Azure服务器上安装VHD驱动器

c# - BlockingCollection<T> 是否保证移除顺序?

c# - 在C#中读取csv文件

c# - 如何将 List<CustomObject> 绑定(bind)到 WPF DataGrid?

c# - 将格式 xxxxxxxxxx 更改为 xxx-xxx-xxxx

c# - 如何更改 WPF 中的 View ?