WPF

[ wpf ] wpf Live chart _ Stack chart 1초마다 업데이트 해보기

code094 2022. 12. 26. 14:56

완성 화면

 

1. NuGet 패키지 관리에서 LiveChart를 다운 받는다. 

2. xaml 에서 네임 스페이스 추가 

3. View 와 ViewModel을 만든다.

4. xaml 디자인 코드 작성 

<Window x:Class="LiveColumnChart.MainWindow"
        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:LiveColumnChart"
        mc:Ignorable="d"
        Background="Transparent"
        xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
        Title="ColumnChart" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="13*"/>
            <ColumnDefinition Width="87*"/>
        </Grid.ColumnDefinitions>
        <lvc:CartesianChart Name="StackChart" Hoverable="False" Series="{Binding SeriesCollection}" Foreground="White" Grid.ColumnSpan="2" LegendLocation="Left">      
            <!-- x 축 -->
            <lvc:CartesianChart.AxisX>
                <lvc:Axis  Labels="{Binding Labels}">
                </lvc:Axis>
            </lvc:CartesianChart.AxisX>
            <!-- y 축 -->
            <lvc:CartesianChart.AxisY>
                <lvc:Axis MinValue="0" >
                    <lvc:Axis.Separator>
                        <lvc:Separator Step="10"/>
                    </lvc:Axis.Separator>
                </lvc:Axis>
            </lvc:CartesianChart.AxisY>
        </lvc:CartesianChart>
    </Grid>
</Window>

5. View 와 VIewModel을 연결한다. 

6. ViewModel 코드 작성 

- 생성할때 한번 ChartList 보여줌 


    public class ChartViewModel
    {
        public SeriesCollection SeriesCollection { get; set; }
        public string[] Labels { get; set; } = new string[] { "Maria", "Sujan" };
        Timer timer = new Timer();
        public ChartViewModel()
        {
            ChartList();          

            timer.Interval = 1000;
            timer.Elapsed += new ElapsedEventHandler(UpdateChart);
            timer.Start();
        }
        public void ChartList()
        {
            var leftChart = new ChartValues<int>();
            var rightChart = new ChartValues<int>();
        
            leftChart.Add(20);
            leftChart.Add(40);
            rightChart.Add(10);
            rightChart.Add(25);

            SeriesCollection = new SeriesCollection
            {
                new ColumnSeries
                {
                    Title = "2021",
                    Values = leftChart
                }
            };
            SeriesCollection.Add(new ColumnSeries
            {
                Title = "2022",
                Values = rightChart
            });
        }
        public void UpdateChart(object source, ElapsedEventArgs e)
        {
            Random rd = new Random();
            int randomNum_1 = rd.Next(30);
            int randomNum_2 = rd.Next(30);
            int randomNum_3 = rd.Next(30);
            int randomNum_4 = rd.Next(30);

            var randomLeftChart = new ChartValues<object>();
            var randomRightChart = new ChartValues<object>();
            DispatcherService.Invoke((System.Action)(() =>
            {
                foreach (var chartCollection in SeriesCollection)
                {
                    chartCollection.Values.Clear();
                    if (chartCollection.Title == "2021")
                    {
                        chartCollection.Values.Add(randomNum_1);
                        chartCollection.Values.Add(randomNum_2);

                    }
                    else
                    {
                        chartCollection.Values.Add(randomNum_3);
                        chartCollection.Values.Add(randomNum_4);
                    }
                }
            }));

        }
        public static class DispatcherService
        {
            public static void Invoke(Action action)
            {
                Dispatcher dispatchObject = Application.Current != null ? Application.Current.Dispatcher : null;
                if (dispatchObject == null || dispatchObject.CheckAccess())
                    action();
                else
                    dispatchObject.Invoke(action);
            }
        }
    }

- 타이머로 1초 마다 업데이트 시킴 (타이머를 쓰기 때문에 Dispatcher 를 사용해주어야 함)