【问题标题】:WPF MVVM LiveCharts how to show X axis Label?WPF MVVM LiveCharts如何显示X轴标签?
【发布时间】:2021-01-08 16:28:07
【问题描述】:

我很难在我的笛卡尔条形图中显示一些简单的标签,我阅读了很多,但似乎没有什么对我有用。我在我的项目中使用 MVVM 模式,所以这是我到目前为止的代码..

查看

<lvc:CartesianChart Grid.Row="2" Series="{Binding ChartDataSets}">
    <lvc:CartesianChart.AxisX>
        <lvc:Axis LabelsRotation="20" Labels="{Binding ColumnLabels}" Position="RightTop" >
            <lvc:Axis.Separator >
                <lvc:Separator Step="1"></lvc:Separator>
            </lvc:Axis.Separator>
        </lvc:Axis>
    </lvc:CartesianChart.AxisX>
    <lvc:CartesianChart.AxisY>
        <lvc:Axis LabelFormatter="{Binding Formatter}" Position="RightTop"></lvc:Axis>
    </lvc:CartesianChart.AxisY>
</lvc:CartesianChart>

数据模型

类数据模型:INotifyPropertyChanged { 私有双值; 公共双值 { 得到 => 这个值; 放 { this.value = 值; OnPropertyChanged(); } }

private string label;
public string Label
{
    get => this.label;
    set
    {
        this.label = value;
        OnPropertyChanged("Label");
    }
}

public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

}

视图模型

class BackupStatsViewModel : INotifyPropertyChanged
{
    ChartValues<DataModel> values = new ChartValues<DataModel>();
    public SeriesCollection ChartDataSets { get; set; }
    public ObservableCollection<string> ColumnLabels { get; set; }
    public class ErrorPrt
    {
        public ErrorPrt(){
            prtName = string.Empty;
            Count = -1;
        }
        public string prtName { get; set; }
        public int Count { get; set; }
    }
    public BackupStatsViewModel()
    {
        InitializeBarChartData();
    }
    private void InitializeBarChartData()
    {

        this.ColumnLabels = new ObservableCollection<string>(values.Select(dataModel => dataModel.Label));
        var dataMapper = new CartesianMapper<DataModel>()
          .Y(dataModel => dataModel.Value)
          .Fill(dataModel => dataModel.Value > 15.0 ? Brushes.Red : Brushes.Green);

        this.ChartDataSets = new SeriesCollection
        {
          new ColumnSeries
          {
            Values = values,
            Configuration = dataMapper,
            DataLabels = true
          }
          
        };
    }
    public ErrorPrt[] PrtCount(List<DataRow> rows)
    {
        IEnumerable<IGrouping<string, DataRow>> grouped = rows.GroupBy(s => s.Field<string>(2));
        ErrorPrt[] err = new ErrorPrt[grouped.Count()];
        //Omitted code for sake of brevity
        
        ErrorPrt[] arr = err.Where(c => c != null).ToArray();
        
        for (int i = 0; i < arr.Count(); i++)
            values.Add(new DataModel() { Label = $"PRT {arr[i].prtName}", Value = arr[i].Count });

        return arr;
    }
 }

但是您可以看到 X 轴上没有显示任何标签.. 真的不知道如何绕过这个问题以便继续我的工作.. 谁能告诉我正确的方法?

【问题讨论】:

  • 如果您查看DataModel.OnPropertyChanged,您将看到CallerMemeberNameAttribute。此属性将自动获取调用成员名称。所以你不需要将属性名称作为字符串传递给这个方法。一般用nameof代替魔术字符串:string propertyName = nameof(this.MyProperty);

标签: c# wpf mvvm livecharts


【解决方案1】:

您的流程看起来中断了:
您首先通过调用InitializeBarChartData() 从构造函数初始化图表数据,这也初始化ColumnLabels 集合。 然后您创建底层的ErrorPtr 项目,它们是列标签数据的提供者。
结果是ColumnLabels 属性为空 => 不会显示任何标签。

因为您将新的ErrorPtr 项目添加到values 字段并且此字段的类型为ChartValues 并且此集合实现INotifyCollectionChanged,所以图表将反映这些更改。你在这里很幸运。

但是因为在创建 ErrorPtr 项后您从未更新 ColumnLabels 属性,所以最初(从构造函数调用 InitializeBarChartData 之后)空的 ColumnLabels 集合仍然是空的。

解决方案 1

修复数据模型初始化流程并调用InitializeBarChartData 之后 PrtCount:

public ErrorPrt[] PrtCount(List<DataRow> rows)
{
    IEnumerable<IGrouping<string, DataRow>> grouped = rows.GroupBy(s => s.Field<string>(2));
    ErrorPrt[] err = new ErrorPrt[grouped.Count()];
    //Omitted code for sake of brevity
    
    ErrorPrt[] arr = err.Where(c => c != null).ToArray();
    
    for (int i = 0; i < arr.Count(); i++)
        this.values.Add(new DataModel() { Label = $"PRT {arr[i].prtName}", Value = arr[i].Count });

    // Initialize the chat models.
    // NOW the label data (the ErrorPrt.prtName) is generated 
    // and ready to be extracted from the ErrorPrt instances
    InitializeBarChartData();

    return arr;
}

解决方案 2(推荐)

由于所有涉及的集合都实现了INotifyCollectionChanged,因此您可以在新数据到达时动态更新每个集合。您无需一遍又一遍地初始化完整的图表数据,如 SeriesCollectionMapper 或标签格式化程序(如在解决方案 1 中 - 以防 PrtCount 将被调用不止一次)。
你可以继续从构造函数中调用一次InitializeBarChartData,就像你现在正在做的那样。

不仅要更新values 字段,还要更新ColumnLabels 属性:

public ErrorPrt[] PrtCount(List<DataRow> rows)
{
    IEnumerable<IGrouping<string, DataRow>> grouped = rows.GroupBy(s => s.Field<string>(2));
    ErrorPrt[] err = new ErrorPrt[grouped.Count()];
    //Omitted code for sake of brevity
    
    ErrorPrt[] arr = err.Where(c => c != null).ToArray();        

    for (int i = 0; i < arr.Count(); i++)
    {    
        var newDataModel = new DataModel() { Label = $"PRT {arr[i].prtName}", Value = arr[i].Count };

        // Here you update the column values
        // and add the new items to the existing items of previous calls
        this.values.Add(newDataModel);

        // Also update the labels whenever new column data has arrived
        this.ColumnLabels.Add(newDataModel.Label);
    }

    return arr;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多