استفاده از نمودارهای MsChart درWPF

در این مقاله، به شما نشان داده می شود که چگونه نمودار کنترل مایکروسافت را در یک UserControl کپسوله سازی کنید که با MVVM سازگار باشد. شما می توانید از این کنترل WPF در برنامه های WPF تان با الگو MVVM و مقید سازی داده (data binding) استفاده نمایید که البته در یک روش مشابه که از کنترل های داخلی WPF استفاده می کنید.

استفاده از نمودارهای MsChart درWPF

مقدمه

همانطور که می دانید شرکت مایکروسافت کنترل نمودار را مشخصا برای winform و ASP.NET توسعه داد که مجموعه گسترده ای را به شما ارائه می داد و دارای همه استاندار های لازم بود از جمله line chart، pie chart و ... . همچنین نمودارهای مخصوصی را نیز به شما نمایش می داد مانند pyramid، bubble، stock و Technical indicator charts. علاوه بر این ویژگی ها و قابلیت ها مجموعه جامع از ویژگی های نمودار، از جمله پشتیبانی از سری های مختلف، سفارشی سازی حرفه ای، برچسب ها را شامل می شود.

متاسفانه، نمودار مایکروسافت مستقیما از WPF و MVVM پشتیبانی نمی کند. شما مجبورید که از عنصر WindowsFormsHost برای میزبانی از نمودار کنترل مایکروسافت اگر شما واقعا می خواهید از آن استفاده کنید در برنامه WPF تان، شما قابلیت مقید سازی (یا data binding) و قواعد MVVM را می شکنید. البته این نکته را هم بدانید که مایکروسافت یک ابزار کنترل نمودار را چند سال پیش برای WPF ارائه داد. با این حال این ابزار محدود است و بسیار کند. کار زیادی هم برای بهینه سازی آن نمی توانید انجام دهید.

سازگارسازی WPF با نمودار کنترل مایکروسافت

در اینجا، یک نمودار کنترل مایکروسافت در داخل یک UserControl در تکنولوژی WPF به نام MsChart با استفاده از عنصر WindowsFormsHost ایجاد می کنیم.

<UserControl x:Class="WpfMsChart.MsChart"

             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 

             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 

             xmlns:mschart="clr-namespace:System.Windows.Forms.DataVisualization.Charting;assembly=System.Windows.Forms.DataVisualization"

             mc:Ignorable="d" 

             d:DesignHeight="300" d:DesignWidth="300">
    <Grid x:Name="grid1" Margin="10">
        <WindowsFormsHost Background="{x:Null}">
            <mschart:Chart x:Name="myChart"/>
        </WindowsFormsHost>
    </Grid>
</UserControl>

این کد XAML بسیار ساده است. ابتدا نیاز داریم تا فضای نام و اسمبلی نمودار کنترل مایکروسافت را به فضای نام XAML اضافه کنیم: System.Windows.Forms.DataVisualization. با استفاده از این فضای نام XML و کلاسی به نام کنترل نمودار Ms ، ما کنترل نمودار را به WindowsFormsHost می افزاییم و نام آن را myChart می گذاریم.

از آنجایی که کنترل اصلی چارت Ms از data binding در wpf پشتیبانی  نمی کند و مدل Mvvm ، ما از کد code-behind برای پیاده سازی این WPF MsChart UserControl استفاده می کنیم. تکه کد زیر پیاده سازی است که برای این کنترل استفاده شده است:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms.DataVisualization.Charting;
using Caliburn.Micro;
using System.Collections.Specialized;

namespace WpfMsChart
{
    /// <summary>
    /// Interaction logic for MsChart.xaml
    /// </summary>
    public partial class MsChart : UserControl
    {
        public MsChart()
        {
            InitializeComponent();
            SeriesCollection = new BindableCollection<Series>();
        }

        public static DependencyProperty XValueTypeProperty = DependencyProperty.Register("XValueType", typeof(string),
            typeof(MsChart), new FrameworkPropertyMetadata("Double", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public string XValueType
        {
            get { return (string)GetValue(XValueTypeProperty); }
            set { SetValue(XValueTypeProperty, value); }
        }

        public static DependencyProperty XLabelProperty = DependencyProperty.Register("XLabel", typeof(string),
            typeof(MsChart), new FrameworkPropertyMetadata("X Axis", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));


        ......


        public BindableCollection<Series> SeriesCollection
        {
            get { return (BindableCollection<Series>)GetValue(SeriesCollectionProperty); }
            set { SetValue(SeriesCollectionProperty, value); }
        }

        private static void OnSeriesChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            var ms = sender as MsChart;
            var sc = e.NewValue as BindableCollection<Series>;
            if (sc != null)
                sc.CollectionChanged += ms.sc_CollectionChanged;
        }

        private void sc_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (SeriesCollection != null)
            {
                CheckCount = 0;
                if (SeriesCollection.Count > 0)
                    CheckCount = SeriesCollection.Count;
            }
        }

        private static DependencyProperty CheckCountProperty = DependencyProperty.Register("CheckCount", typeof(int),
            typeof(MsChart), new FrameworkPropertyMetadata(0, StartChart));

        private int CheckCount
        {
            get { return (int)GetValue(CheckCountProperty); }
            set { SetValue(CheckCountProperty, value); }
        }

        private static void StartChart(object sender, DependencyPropertyChangedEventArgs e)
        {
            var ms = sender as MsChart;
            if (ms.CheckCount > 0)
            {
                ms.myChart.Visible = true;
                ms.myChart.Series.Clear();
                ms.myChart.Titles.Clear();
                ms.myChart.Legends.Clear();
                ms.myChart.ChartAreas.Clear();

                MSChartHelper.MyChart(ms.myChart, ms.SeriesCollection, ms.Title, ms.XLabel, ms.YLabel, ms.ChartBackground, ms.Y2Label);
                if (ms.myChart.ChartAreas.Count > 0)
                    ms.myChart.ChartAreas[0].Area3DStyle.Enable3D = ms.IsArea3D;

                ms.myChart.DataBind();
            }
            else
                ms.myChart.Visible = false;
        }

        ......

    }
}

اکنون از Caliburn.Macro به عنوان چارچوب MVVM مان استفاده می کنیم. درواقع بصورت معمول برای تبدیل خواص کنترل نمودارهایمان به خواص وابستگی استفاده می کنیم. در بعضی از موقعیت ها قصد دارید تا مقداری کد منطقی اجرا کنید و متد های محاسباتی داشته باشید بعد از اینکه مقادیر را برای خواص وابستگی تنظیم کردید. می توانید این عملیات را به وسیله یک متد بازگشتی اجرا کنید درست زمانی که خاصیت wrapper تغییر می کند یا متد SetValue صدا زده می شود. به عنوان مثال، بعد از ساختن SeriesCollection که شامل اشیاء می شود. قطعه کد در code-behind ماقبل به شما نشان دادیم که چگونه یک متد بازگشتی پیاده سازی کنید. این خاصیت SeriesCollectionProperty شامل یک متد بازگشتی می شود به نام OnSeriesChanged. در داخل این متد بازگشتی، یک مدیریت رویداد به CollectionChanged اضافه کنید و آن آغاز به اجرا کردن می کند درست زمانی که SeriesCollection تغییر کند. در داخل CollectionChanged handler، یک خاصیت وابستگی دیگری وجود دارد به نام CheckCount برای SeriesCollection.Count. اگر CheckCount > 0 باشد، ما متوجه می شویم که SeriesCollection شامل اشیائی است و سپس متد بازگشتی آن را پیاده سازی می کنیم و آن را StartChart نام گذاری می کنیم برای خاصیت CheckCount که یک نمودار به وسیله متد پیاده سازی شده به نام MyChart در کلاس MSChartHelper می سازد. متد هایی که در داخل کلاس MSChartHelper هستند به سادگی انواع متفاوتی از نمودار های از پیش تعریف شده را دارد، که در ادامه مقاله آن ها را معرفی می کنیم.

شما می توانید DataSource را از طریق خاصیت وابستگی به DataSource کنترل نمودارتان متصل کنید. خاصیت وابستگی Chart1 به شما اجازه می دهد تا به کنترل نمودار مایکروسافت بصورت مستقیم دسترسی داشته باشید اگر نوع نموداری که می خواهید در میان نمودار های از پیش تعریف شده قرار ندارد، آن را در کلاس MSChartHelper پیاده سازی کنید.

کلاس Helper

در بخش قبل، ما یک کنترل MsChart در WPF ساختیم، که کپسوله شد در کنترل نمودار مایکروسافت (نسخه Windiows Form). متد StartChart در کنترل MsChart صدا می زند متد MyChart را در کلاس MSChartHelper. شما می توانید همچنین نمودار خودتان را بسازید البته مطابق با نیازمندی های برنامه تان از برنامه ها با کنترل روند که در اینجا ارائه شده است. مزیت انجام اینکار این است که شما نیاز نیست انواع Styleهای نمودار را بسازید هر بار که نمودار می خواهید بسازید. قرار دهید chart-style را با کد مرتبطش در یک جا قرار دهید برای اینکه یک قالب Reusable داشته باشید. شما می توانید هربار که می خواهید می توانید Chart-Style را به راحتی تغییر دهید. برای مثال اگر شما می خواهید همه نمودار هایتان پس زمینه آبی داشته باشند، شما به سادگی می توانید آن را در قالبتان یک بار تغییر دهید و دیگر نیازی نیست تا هربار برای هر نمودار آن را تغییر دهید.


using System.Collections.Generic;

using System.Windows.Forms.DataVisualization.Charting;

using System.Drawing;

using Caliburn.Micro;



namespace WpfMsChart

{

    public static class MSChartHelper

    {

        public static void MyChart(Chart chart1, BindableCollection<Series> chartSeries, string chartTitle, string xLabel, string yLabel, ChartBackgroundColor backgroundColor, params string[] y2Label)

        {

            if (chart1.ChartAreas.Count < 1)

            {

                ChartArea area = new ChartArea();

                ChartStyle(chart1, area, backgroundColor);

            }



            if (chartTitle != "")

                chart1.Titles.Add(chartTitle);

            chart1.ChartAreas[0].AxisX.Title = xLabel;

            chart1.ChartAreas[0].AxisY.Title = yLabel;

            if (y2Label.Length > 0)

                chart1.ChartAreas[0].AxisY2.Title = y2Label[0];



            foreach (var ds in chartSeries)

                chart1.Series.Add(ds);



            if (chartSeries.Count > 1)

            {

                Legend legend = new Legend();

                legend.Font = new System.Drawing.Font("Trebuchet MS", 7.0F, FontStyle.Regular);

                legend.BackColor = Color.Transparent;

                legend.AutoFitMinFontSize = 5;

                legend.LegendStyle = LegendStyle.Column;



                legend.IsDockedInsideChartArea = true;

                legend.Docking = Docking.Left;

                legend.InsideChartArea = chart1.ChartAreas[0].Name;

                chart1.Legends.Add(legend);

            }        

        }



        public static void ChartStyle(Chart chart1, ChartArea area, ChartBackgroundColor backgroundColor)

        {

            int r1 = 211;

            int g1 = 223;

            int b1 = 240;

            int r2 = 26;

            int g2 = 59;

            int b2 = 105;

            int r3 = 165;

            int g3 = 191;

            int b3 = 228;



            switch (backgroundColor)

            {

                case ChartBackgroundColor.Blue:

                    chart1.BackColor = Color.FromArgb(r1, g1, b1);

                    chart1.BorderlineColor = Color.FromArgb(r2, g2, b2);

                    area.BackColor = Color.FromArgb(64, r3, g3, b3);

                    break;

                case ChartBackgroundColor.Green:

                    chart1.BackColor = Color.FromArgb(g1, b1, r1);

                    chart1.BorderlineColor = Color.FromArgb(g2, b2, r2);

                    area.BackColor = Color.FromArgb(64, g3, b3, r3);

                    break;

                case ChartBackgroundColor.Red:

                    chart1.BackColor = Color.FromArgb(b1, r1, g1);

                    chart1.BorderlineColor = Color.FromArgb(b2, r2, g2);

                    area.BackColor = Color.FromArgb(64, b3, r3, g3);

                    break;

                case ChartBackgroundColor.White:

                    chart1.BackColor = Color.White;

                    chart1.BorderlineColor = Color.White;

                    area.BackColor = Color.White;

                    break;

            }



            if (backgroundColor != ChartBackgroundColor.White)

            {

                chart1.BackSecondaryColor = Color.White;

                chart1.BackGradientStyle = GradientStyle.TopBottom;

                chart1.BorderlineDashStyle = ChartDashStyle.Solid;

                chart1.BorderlineWidth = 2;

                chart1.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;



                area.Area3DStyle.IsClustered = true;

                area.Area3DStyle.Perspective = 10;

                area.Area3DStyle.IsRightAngleAxes = false;

                area.Area3DStyle.WallWidth = 0;

                area.Area3DStyle.Inclination = 15;

                area.Area3DStyle.Rotation = 10;

            }



            area.AxisX.IsLabelAutoFit = false;

            area.AxisX.LabelStyle.Font = new Font("Trebuchet MS", 7.25F, FontStyle.Regular);

            //area.AxisX.LabelStyle.IsEndLabelVisible = false;

            area.AxisX.IntervalAutoMode = IntervalAutoMode.VariableCount;

            area.AxisX.LineColor = Color.FromArgb(64, 64, 64, 64);

            area.AxisX.MajorGrid.LineColor = Color.FromArgb(64, 64, 64, 64);

            area.AxisX.IsStartedFromZero = false;

            area.AxisX.RoundAxisValues();



            area.AxisY.IsLabelAutoFit = false;

            area.AxisY.LabelStyle.Font = new Font("Trebuchet MS", 7.25F, System.Drawing.FontStyle.Regular);

            area.AxisY.LineColor = Color.FromArgb(64, 64, 64, 64);

            area.AxisY.MajorGrid.LineColor = Color.FromArgb(64, 64, 64, 64);

            area.AxisY.IsStartedFromZero = false;

           

            area.AxisY2.IsLabelAutoFit = false;

            area.AxisY2.LabelStyle.Font = new Font("Trebuchet MS", 7.25F, System.Drawing.FontStyle.Regular);

            area.AxisY2.LineColor = Color.FromArgb(64, 64, 64, 64);

            area.AxisY2.MajorGrid.LineColor = Color.FromArgb(15, 15, 15, 15);

            area.AxisY2.IsStartedFromZero = false;



            area.BackSecondaryColor = System.Drawing.Color.White;

            area.BackGradientStyle = GradientStyle.TopBottom;

            area.BorderColor = Color.FromArgb(64, 64, 64, 64);

            area.BorderDashStyle = ChartDashStyle.Solid;

            area.Position.Auto = false;

            area.Position.Height = 82F;

            area.Position.Width = 88F;

            area.Position.X = 3F;

            area.Position.Y = 10F;

            area.ShadowColor = Color.Transparent;



            chart1.ChartAreas.Add(area);

            chart1.Invalidate();

        }



        public static List<System.Drawing.Color> GetColors()

        {           

            List<Color> my_colors = new List<Color>();

            my_colors.Add(Color.DarkBlue);

            my_colors.Add(Color.DarkRed);

            my_colors.Add(Color.DarkGreen);

            my_colors.Add(Color.Black);

            my_colors.Add(Color.DarkCyan);

            my_colors.Add(Color.DarkViolet);

            my_colors.Add(Color.DarkOrange);

            my_colors.Add(Color.Maroon);

            my_colors.Add(Color.SaddleBrown);

            my_colors.Add(Color.DarkOliveGreen);



            return my_colors;

        }

    }



    public enum ChartBackgroundColor

    {

        Blue = 0,

        Green = 1,

        Red = 2,

        White = 3,

    }

}

کد زیر برای کلاس MSChartHelper است:

متد Mychart یک chart1، chartSeries، chartTitle، xLabel، yLabel، BackgroundColor و y2Label  به عنوان آرگومان های ورودی می گیرد. پارامتر chart1  مستقیما تخصیص داده می شود به myChart در MsChart Control و همه پارامتر های دیگر در خواص وابستگی (dependency property) در کد پشت صحنه MsChartControl تعریف می شوند. متد MyChart  همچنین یک متد دیگر به نام ChartStyle، که تعریف می کند از انواع متنوع chart-style مربوط است به خواصی مانند BackgroundColor، Blue، Green، Red و White با استفاده از ChartBackgroundColorEnum. شما می توانید به راحتی انواع دیگر رنگ های پس زمینه را همانطور که می خواهید تنظیم کنید. ما همچنین می توانیم بسازیم یک لیست از 10 رنگ از پیش تعریف شده توسط متد GetColors که ما می توانیم از آن ها برای مشخص کردن رنگ ها در سریال نمودار هایمان استفاده نماییم.

ساخت نمودار ها با استفاده از کنترل MsChart در WPF

در این قسمت، ما می خواهیم از یک مثال استفاده کنیم تا به شما نشان دهیم چطور ساختن نمودارهای متفاوت با استفاده از کنترل MsChart پیاده سازی می کند در بخش های قبل. کدی که در ادامه نوشتیم برایتان یک فایل XAML است که به نام MainView در اینجا نام گذاری شده است:

<Window x:Class="WpfMsChart.MainView"



        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"



        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"



        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"



        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"



        xmlns:local="clr-namespace:WpfMsChart"



        xmlns:cal="http://www.caliburnproject.org"



        mc:Ignorable="d"



        Title="MainView" Height="300" Width="500">

    <Grid Margin="10">

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="150"/>

            <ColumnDefinition Width="*"/>

        </Grid.ColumnDefinitions>

        <StackPanel>

            <Button x:Name="BarChart" Content="Bar Chart" Width="120" Margin="0 10 0 0"/>

            <Button x:Name="LineChart" Content="Line Chart" Width="120" Margin="0 10 0 0"/>



            <Button x:Name="PieChart" Content="Pie Chart" Width="120" Margin="0 10 0 0"/>

            <Button x:Name="PolarChart" Content="Polar Chart" Width="120" Margin="0 10 0 0"/>

        </StackPanel>



        <Grid Grid.Column="1">

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="*"/>

                <ColumnDefinition Width="*"/>

            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>

                <RowDefinition Height="*"/>

                <RowDefinition Height="*"/>

            </Grid.RowDefinitions>



            <local:MsChart SeriesCollection="{Binding BarSeriesCollection}" ChartBackground="Blue" Title="Bar Chart"/>

            <local:MsChart SeriesCollection="{Binding LineSeriesCollection}" ChartBackground="Red" Title="Line Chart" Grid.Column="1"/>

            <local:MsChart SeriesCollection="{Binding PieSeriesCollection}" ChartBackground="Green" Title="Pie Chart" Grid.Row="1" IsArea3D="True"/>

            <local:MsChart SeriesCollection="{Binding PolarSeriesCollection}" ChartBackground="White" Title="Polar Chart" XLabel="" YLabel="" Grid.Row="1" Grid.Column="1"/>

        </Grid>

    </Grid>

</Window>



با استفاده از فضای نام و کلاس user control، MsChart ما کنترل را دقیقا همانطور که می خواهیم اضافه می کنیم و انواع دیگری از شیئ را در فایل XAML، حتی اگر کنترل MsChart شامل Windows Forms MS chart control باشد که میزبانی شده بود در یک WindowsFormsHost. شما می توانید مشاهده کنید که در این مثال، ما می خواهیم چهار مثال ساده از نمودار ها، including bar،  line، pie و polar charts. در این مورد ما باید مشخص کنیم یک خاصیت کلید، SeriesCollection که نگه داری می کند از سریال نمودار ها و باید تعریف شود در ViewModel.

در اینجا چند کد مرتبط با ViewModel قرار گرفته است:

using System;

using Caliburn.Micro;

using System.Windows.Forms.DataVisualization.Charting;



namespace WpfMsChart

{

    public class MainViewModel : PropertyChangedBase

    {

        public BindableCollection<Series> BarSeriesCollection { get; set; }

        public BindableCollection<Series> LineSeriesCollection { get; set; }

        public BindableCollection<Series> PieSeriesCollection { get; set; }

        public BindableCollection<Series> PolarSeriesCollection { get; set; }



        public MainViewModel()

        {

            BarSeriesCollection = new BindableCollection<Series>();

            LineSeriesCollection = new BindableCollection<Series>();

            PieSeriesCollection = new BindableCollection<Series>();

            PolarSeriesCollection = new BindableCollection<Series>();

        }



        public void BarChart()

        {

            double[] data1 = new double[] { 32, 56, 35, 12, 35, 6, 23 };

            double[] data2 = new double[] { 67, 24, 12, 8, 46, 14, 76 };



            BarSeriesCollection.Clear();

            Series ds = new Series();

            ds.ChartType = SeriesChartType.Column;

            ds["DrawingStyle"] = "Cylinder";

            ds.Points.DataBindY(data1);

            BarSeriesCollection.Add(ds);



            ds = new Series();

            ds.ChartType = SeriesChartType.Column;

            ds["DrawingStyle"] = "Cylinder";

            ds.Points.DataBindY(data2);

            BarSeriesCollection.Add(ds);

        }



        public void LineChart()

        {

            LineSeriesCollection.Clear();

            Series ds = new Series();

            ds.ChartType = SeriesChartType.Line;

            ds.BorderDashStyle = ChartDashStyle.Solid;

            ds.MarkerStyle = MarkerStyle.Diamond;

            ds.MarkerSize = 8;

            ds.BorderWidth = 2;

            ds.Name = "Sine";

            for (int i = 0; i < 70; i++)

            {

                double x = i / 5.0;

                double y = 1.1 * Math.Sin(x);

                ds.Points.AddXY(x, y);

            }

            LineSeriesCollection.Add(ds);



            ds = new Series();

            ds.ChartType = SeriesChartType.Line;

            ds.BorderDashStyle = ChartDashStyle.Dash;

            ds.MarkerStyle = MarkerStyle.Circle;

            ds.MarkerSize = 8;

            ds.BorderWidth = 2;

            ds.Name = "Cosine";

            for (int i = 0; i < 70; i++)

            {

                double x = i / 5.0;

                double y = 1.1 * Math.Cos(x);

                ds.Points.AddXY(x, y);

            }

            LineSeriesCollection.Add(ds);

        }



        public void PieChart()

        {

            PieSeriesCollection.Clear();

            Random random = new Random();

            Series ds = new Series();

            for (int i = 0; i < 5; i++)

                ds.Points.AddY(random.Next(10, 50));

            ds.ChartType = SeriesChartType.Pie;

            ds["PointWidth"] = "0.5";

            ds.IsValueShownAsLabel = true;

            ds["BarLabelStyle"] = "Center";

            ds["DrawingStyle"] = "Cylinder";

            PieSeriesCollection.Add(ds);

        }



        public void PolarChart()

        {

            PolarSeriesCollection.Clear();

            Series ds = new Series();

            ds.ChartType = SeriesChartType.Polar;

            ds.BorderWidth = 2;

            for (int i = 0; i < 360; i++)

            {

                double x = 1.0 * i;

                double y = 0.001 + Math.Abs(Math.Sin(2.0 * x * Math.PI / 180.0) * Math.Cos(2.0 * x * Math.PI / 180.0));

                ds.Points.AddXY(x, y);

            }

            PolarSeriesCollection.Add(ds);



        }

    }

}

در اینجا ما چهار Series Collection و چهار متد تعریف کردیم. که استفاده شده اند در bar، line، pie و polar charts. اگر شما حتی استفاده می کردید از کنترل MSChart در Windows Forms Applications قبل از این شما باید آشنا شوید با قطعه کد داخل هر متد. ما اشیاء Series را در داخل هر متد ساختیم و اضافه کردیم اشیاء series را به series collection های متناظر که داده در مقید شده است برای کنترل MsChart  که در view تعریف شده است. با کمک این روش، ما می توانیم اضافه کنیم MSChart را به داخل برنامه WPF با استفاده از الگوی MVVM.

نتیجه گیری

در این مقاله آموختید که چگونه از MS Chart Control در یک برنامه WPF و MVVM استفاده کنید. همچنین چگونگی گسترش و توسعه این نمودار ها را هم به شما آموزش دادیم.

فایل های ضمیمه
دانلود نسخه ی PDF این مطلب