在MVVM模式下使用C1Chart(二)

发布时间:2014/11/02 00:11 发布者:Alice

返回博客中心

在上一篇中,我们介绍了在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/

本系列同步文章参考

C1Chart在WinForm平台下的同步(一):滚动条同步

C1Chart在WinForm平台下的同步(二):缩放同步

C1Chart在WinForm平台下的同步(三):TriangleMarker同步


关于葡萄城

赋能开发者!葡萄城是专业的集开发工具、商业智能解决方案、低代码开发平台于一身的软件和服务提供商,为超过 75% 的全球财富 500 强企业提供服务。葡萄城专注控件软件领域30年,希望通过模块化的开发控件、灵活的低代码应用开发平台等一系列开发工具、解决方案和服务,帮助开发者快速响应复杂多变的业务需求,最大程度地发挥开发者的才智和潜能,让开发者的 IT 人生更从容更美好。

了解详情,请访问葡萄城官网