在上一篇中,我们介绍了在MVVM模式下使用C1Chart(一)。那么如何在C1Chart动态的添加和删除数据序列。本文就在上一节的基础上,就此内容展开讨论。
如果我们在C1chart的model下有大量的bindings,那么ChartData需要接受一个binding。我们可以简单的设计一个C1ChartData属性,暴露在ViewModel,然后运行时从这个ChartData添加和删除序列。
在下面我们通过实现,让用户更加清楚地了解。
首先,需要在VisualStudio创建一个WPF工程。在Sales类的基础上展示数据。因此我们需要创建这个类。
代码如下:
public class Sales:INotifyPropertyChanged { public Sales(string product,double salevalue,double volume,string shipcity,double discount) { _product = product; _salevalue = salevalue; _volume = volume; _shipcity = shipcity; _discount = discount; _variance = (_volume*1000/_salevalue); } #region privateFields string _product; double _salevalue; double _volume; double _discount; string _shipcity; double _variance; #endregion #region publicProperties public string Product { get { return _product; } set { _product = value; } } public double SaleValue { get { return _salevalue; } set { _salevalue = value; OnPropertyChanged("SaleValue"); } } public double Volume { get { return _volume; } set { _volume = value; OnPropertyChanged("Volume"); } } public double Discount { get { return _discount; } set { _discount = value; OnPropertyChanged("Discount"); } } public double Variance { get { return (this.Volume*1000/ this.SaleValue); } } public string ShipCity { get { return _shipcity; } set { _shipcity = value; OnPropertyChanged("ShipCity"); } } #endregion #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string property) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } } #endregion }
在这个类中,我们有六个fields:Salevalue (产品的销售价格), Volume (产品的出售体积), Discount (产品折扣), ShipCity (发货城市), and Variance (假设方差)。
接下来,我们需要创建ViewModelBase从INotifyPropertyChanged 接口继承。我们的ChartViewModel将从这个base viewmodel继承。
如下是base viewmode代码:
public class ViewModelBase:INotifyPropertyChanged { #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string property) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } } #endregion public ViewModelBase() { } }
现在就可以创建ChartViewModel。如下是代码:
public class ChartViewModel:ViewModelBase { #region Ctor.. public ChartViewModel() { _saleslist = new ObservableCollection(); LoadData(); _axisvalues = new ObservableCollection(); _axisvalues.Add("SaleValue"); _axisvalues.Add("Volume"); _axisvalues.Add("VolumeVsCity"); _axisvalues.Add("ProductDiscount"); _axisvalues.Add("VolumeTotal"); _axisview = new CollectionView(_axisvalues); _axisview.CurrentChanged += new EventHandler(_axisview_CurrentChanged); _chartdata = new ChartData(); ChartDataView.ItemNameBinding = new Binding("Product"); DataSeries ds1 = new DataSeries(); ds1.Label = "SaleValue"; ds1.ValueBinding = new Binding("SaleValue"); DataSeries ds2 = new DataSeries(); ds2.Label = "Volume"; ds2.ValueBinding = new Binding("Volume"); ChartDataView.ItemsSource = SalesList; ChartDataView.Children.Add(ds1); ChartDataView.Children.Add(ds2); } #endregion #region private Fields ObservableCollection _saleslist; ObservableCollection _axisvalues; CollectionView _axisview; ChartData _chartdata; #endregion #region publicProperties public ObservableCollection SalesList { get { return _saleslist; } set { _saleslist = value; } } public CollectionView AxisView { get { return _axisview; } set { _axisview = value; OnPropertyChanged("AxisView"); } } public ChartData ChartDataView { get { return _chartdata; } set { _chartdata = value; OnPropertyChanged("ChartDataView"); } } #endregion #region privateMethods void LoadData() { _saleslist.Add(new Sales("Confectionaries", 2500.00,300000.00,"NewYork",25.50)); _saleslist.Add(new Sales("Plastics", 3500.00,720000.00,"Newark",15.75)); _saleslist.Add(new Sales("Electronics", 7500.00,800000.00,"GeorgeTown",20.65)); _saleslist.Add(new Sales("Produces", 800.00,100000.00,"Houston",30.35)); } void _axisview_CurrentChanged(object sender, EventArgs e) { if (_axisview.CurrentItem.ToString() == "SaleValue") { _chartdata.Children.Clear(); DataSeries ds1 = new DataSeries(); ds1.Label = "SaleValue"; ds1.ValueBinding = new Binding("SaleValue"); ds1.ItemsSource = SalesList; _chartdata.Children.Add(ds1); _chartdata.ItemNameBinding = new Binding("Product"); } else if (_axisview.CurrentItem.ToString() == "Volume") { _chartdata.Children.Clear(); DataSeries ds2 = new DataSeries(); ds2.ValueBinding = new Binding("Volume"); ds2.Label = "Volume"; ds2.ItemsSource = SalesList; _chartdata.Children.Add(ds2); _chartdata.ItemNameBinding = new Binding("Product"); } else if (_axisview.CurrentItem.ToString() == "VolumeVsCity") { _chartdata.Children.Clear(); DataSeries ds1 = new DataSeries(); ds1.Label="Volume"; ds1.ValueBinding = new Binding("Volume"); ds1.ItemsSource = SalesList; _chartdata.Children.Add(ds1); _chartdata.ItemNameBinding = new Binding("ShipCity"); } else if (_axisview.CurrentItem.ToString() == "ProductDiscount") { _chartdata.Children.Clear(); DataSeries ds1 = new DataSeries(); ds1.Label = "Discount"; ds1.ValueBinding = new Binding("Discount"); ds1.ItemsSource = SalesList; _chartdata.Children.Add(ds1); _chartdata.ItemNameBinding = new Binding("Product"); } else if (_axisview.CurrentItem.ToString() == "VolumeTotal") { _chartdata.Children.Clear(); DataSeries ds1 = new DataSeries(); ds1.Label = "Volume"; ds1.ValueBinding = new Binding("Volume"); ds1.ItemsSource = SalesList; DataSeries ds2 = new DataSeries(); ds2.Label = "Variance"; ds2.ValueBinding = new Binding("Variance"); ds2.ItemsSource = SalesList; _chartdata.Children.Add(ds1); _chartdata.Children.Add(ds2); _chartdata.ItemNameBinding = new Binding("Product"); } } #endregion }
好了,检查下上述代码。有一个LoadData方法,可以导入数据到ObservableCollection<Sales> SalesList。这是一个ObservableCollection<string> _axisvalues 集合,暴露了在运行时要用的dataseries。我们需要在构造器里,添加变量值到这个集合。
另外,ChartDataView属性是ChartData类型。在构造器我们需要创建两个序列然后添加到ChartData。
现在当序列从ChartData添加或删除的时候,我们需要_axisview_CurrentChanged事件。_axisview是 _axisvalues的collectionview 。在这个事件里,检查当前的选择和添加一个序列到chartdata。
于是,我们需要绑定C1chart的Data属性到viewmodel的ChartDataView。因此,如下是在应用程序里的基本UI XAML代码:
<Window x:Class="C1ChartinMVVMPart2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="336" Width="790" xmlns:c1chart="http://schemas.componentone.com/xaml/c1chart"> <Grid x:Name="LayoutRoot" > <c1chart:C1Chart Height="276" HorizontalAlignment="Left" Margin="153,9,0,0" Name="c1Chart1" VerticalAlignment="Top" Width="603" Data="{Binding ChartDataView}" Theme="{DynamicResource {ComponentResourceKey ResourceId=Vista, TypeInTargetAssembly=c1chart:C1Chart}}"> <c1chart:C1ChartLegend DockPanel.Dock="Right" /> </c1chart:C1Chart> <ListBox Height="100" ItemsSource="{Binding AxisView}" HorizontalAlignment="Left" Margin="27,98,0,0" Name="listBox1" VerticalAlignment="Top" Width="120" Background="{Binding ElementName=c1Chart1,Path=Background}"/> </Grid> </Window>将AXisView collectionview暴露给ListBox。这个Listbox就能展示所有可用的数据序列,然后将相关的数据序列画在C1chart中。添加如下代码在Application的startup事件。MainWindow win = new MainWindow(); C1ChartinMVVMPart2.ViewModel.ChartViewModel vm = new ViewModel.ChartViewModel(); win.LayoutRoot.DataContext = vm; win.Show();
运行程序就能看到行为。
如下是本文的Demo:
C1ChartinMVVMPart2.zip (19.45 kb)
如果你对C1Chart感兴趣,请到我们的官网下载最新版本:/developer
如果你有疑问,可以到GCDN论坛获得技术支持:http://gcdn.grapecity.com.cn/
本系列同步文章参考: