ViewModel中有一个水平条形图,显示了过去6个月或12个月内排名前10的客户端(默认值为6(。当用户点击按钮时,我希望数据切换到6个月或12个月。我似乎不知道如何更新图表。我已经实现了INotifyPropertyChanged
接口,但我一定做错了。我已经读了很多关于这个主题的帖子:仍然不知道哪里出了问题。
图表的屏幕截图
ReportClientModel
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace ReportXpress.Models
{
public class ReportClientModel : INotifyPropertyChanged
{
private string name;
public string Name
{
get => this.name;
set
{
this.name = value;
OnPropertyChanged();
}
}
public double? sales;
public double? Sales
{
get => this.sales;
set
{
this.sales = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName=null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
ViewModelBase
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
namespace ReportXpress.ViewModels
{
// Abstract : can only be used via inheritance
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
ClientViewModel
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using SkiaSharp;
using System.Collections.ObjectModel;
using System.Drawing;
using LiveChartsCore.Defaults;
using ReportXpress.Models;
using ReportXpress.Repositories;
using Org.BouncyCastle.Tls;
using System.Windows.Input;
using System.ComponentModel;
namespace ReportXpress.ViewModels
{
public class ClientViewModel : ViewModelBase
{
//Fields
private ObservableCollection<ISeries> clientsSalesSeries;
public ReportClientModel[] topClients6Months;
public ReportClientModel[] topClients12Months;
//Properties
public ObservableCollection<ISeries> ClientsSalesSeries
{ get
{
return clientsSalesSeries;
}
set
{
clientsSalesSeries = value;
OnPropertyChanged(nameof(ClientsSalesSeries));
}
}
public string[] Labels { get; set; }
public LiveChartsCore.Measure.Margin Margin { get; set; } = new LiveChartsCore.Measure.Margin(25,0,150,50);
//Events
public new event PropertyChangedEventHandler PropertyChanged;
//--> Commands
public ICommand ShowLast6Months { get; }
public ICommand ShowLast12Months { get; }
public ClientViewModel()
{
//Initialize commands
ShowLast6Months = new ViewModelCommand(ExecuteShowLast6Months);
ShowLast12Months = new ViewModelCommand(ExecuteShowLast12Months);
topClients6Months = new ReportClientModel[]
{
new ReportClientModel { Name = "Client 10 name", Sales=30689 },
new ReportClientModel { Name = "Client 9 name", Sales=31558 },
new ReportClientModel { Name = "Client 8 name", Sales=38937 },
new ReportClientModel { Name = "Client 7 name", Sales=42139 },
new ReportClientModel { Name = "Client 6 name", Sales=49860 },
new ReportClientModel { Name = "Client 5 name", Sales=51561 },
new ReportClientModel { Name = "Client 4 name", Sales=69554 },
new ReportClientModel { Name = "Client 3 name", Sales=70524 },
new ReportClientModel { Name = "Client 2 name", Sales=276170 },
new ReportClientModel { Name = "Client 1 name", Sales=345835 }
};
topClients12Months = new ReportClientModel[]
{
new ReportClientModel { Name = "Client 10 name", Sales=56664 },
new ReportClientModel { Name = "Client 9 name", Sales=79135 },
new ReportClientModel { Name = "Client 8 name", Sales=80280 },
new ReportClientModel { Name = "Client 7 name", Sales=83675 },
new ReportClientModel { Name = "Client 6 name", Sales=92612 },
new ReportClientModel { Name = "Client 5 name", Sales=126429 },
new ReportClientModel { Name = "Client 4 name", Sales=158313 },
new ReportClientModel { Name = "Client 3 name", Sales=163430 },
new ReportClientModel { Name = "Client 2 name", Sales=442796 },
new ReportClientModel { Name = "Client 1 name", Sales=592028 }
};
//Default values : last 6 months
ExecuteShowLast6Months(null);
Formatter = value => value.ToString("0") + " k$";
}
protected virtual new void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void ExecuteShowLast12Months(object obj)
{
ClientsSalesSeries = new ObservableCollection<ISeries>
{
new RowSeries<ReportClientModel>
{
Values = topClients12Months,
Mapping = (client, point) =>
{
// use the Sales property in this series
point.PrimaryValue = (float)client.Sales;
// use the Index of the item
point.SecondaryValue = point.Context.Entity.EntityIndex;
},
Fill = new SolidColorPaint(SKColors.SkyBlue),
TooltipLabelFormatter = (point) => point.PrimaryValue.ToString("C2"),
DataLabelsPaint = new SolidColorPaint(SKColors.White),
DataLabelsSize = 14,
DataLabelsPosition = LiveChartsCore.Measure.DataLabelsPosition.End,
DataLabelsFormatter = (point) => topClients6Months[point.Context.Entity.EntityIndex].Name,
}
};
}
private void ExecuteShowLast6Months(object obj)
{
ClientsSalesSeries = new ObservableCollection<ISeries>
{
new RowSeries<ReportClientModel>
{
Values = topClients6Months,
Mapping = (client, point) =>
{
// use the Sales property in this series
point.PrimaryValue = (float)client.Sales;
// use the Index of the item
point.SecondaryValue = point.Context.Entity.EntityIndex;
},
Fill = new SolidColorPaint(SKColors.SkyBlue),
TooltipLabelFormatter = (point) => point.PrimaryValue.ToString("C2"),
DataLabelsPaint = new SolidColorPaint(SKColors.White),
DataLabelsSize = 14,
DataLabelsPosition = LiveChartsCore.Measure.DataLabelsPosition.End,
DataLabelsFormatter = (point) => topClients6Months[point.Context.Entity.EntityIndex].Name,
}
};
}
public Axis[] XAxesAmounts { get; set; } =
{
new Axis
{
LabelsPaint = new SolidColorPaint{ Color= SKColors.White},
Labeler = Labelers.Currency,
NameTextSize=10,
ShowSeparatorLines=true,
SeparatorsPaint = new SolidColorPaint { Color = SKColor.Parse("#33ffffff")},
TextSize=10
}
};
public Axis[] YAxesClients { get; set; } =
{
new Axis
{
Name = "",
NamePaint = new SolidColorPaint{ Color=SKColors.White},
LabelsPaint = new SolidColorPaint{ Color= SKColors.White},
Labeler = null,
IsVisible = true,
NameTextSize=10,
LabelsRotation=0,
ShowSeparatorLines = false,
MinLimit=-0.5,
TextSize=10
}
};
}
}
ClientView(仅图表部分(
<!--Chart for Top Clients-->
<lvc:CartesianChart Grid.Row="1" Margin="0,0,0,15"
Name="chartClientSales"
Series="{Binding ClientsSalesSeries}"
XAxes="{Binding XAxesAmounts}"
YAxes="{Binding YAxesClients}"
DrawMargin="{Binding Margin}"
TooltipPosition="Right"
ZoomMode="Both"
/>
在ExecuteShowLast12Months
中添加断点可确认序列中的数据已更改,但图表不会更新以反映新数据。我做错了什么?我还没有看到任何其他在RowSeries中使用自定义类的帖子。
您有两个选项
- 通过清除ObservableCollection并直接向其中添加新数据来更新系列(这样就不必实现INotifyPropertyChanged(
public ObservableCollection<ISeries> ClientsSalesSeries {set; get;} = new();
// ...
private void ExecuteShowLast12Months(object obj)
{
ClientsSalesSeries.Clear();
ClientsSalesSeries.Add(new RowSeries<ReportClientModel>{ });
}
// ...
private void ExecuteShowLast6Months(object obj)
{
ClientsSalesSeries.Clear();
ClientsSalesSeries.Add(new RowSeries<ReportClientModel>{ });
}
- 将
Series
的绑定模式设置为TwoWay(您可以使用任何集合,例如List(
Series="{Binding ClientsSalesSeries, Mode=TwoWay}"
如果您想利用ObservableCollection,则首选第一个选项。