! 제품 버전을 정확하게 입력해 주세요.
제품 버전이 정확하게 기재되어 있지 않은 경우,
최신 버전을 기준으로 안내 드리므로
더욱 빠르고 명확한 안내를 위해
제품 버전을 정확하게 입력해 주세요!

FlexChart WPF Chart 컨트롤의 비동기 드릴다운 옵션 > 온라인 스터디

본문 바로가기

ComponentOne

온라인 스터디

WPF FlexChart WPF Chart 컨트롤의 비동기 드릴다운 옵션

페이지 정보

작성자 GrapeCity 작성일 2022-10-12 09:11 조회 563회 댓글 0건

본문

첨부파일

우리는 데이터를 시각화하고 분석할 때 자주 차트를 사용합니다. 그러나 차트는 플랫(비관계형) 데이터만 시각화할 수 있습니다. 그러나 데이터가 관계형이거나 계층 구조를 포함하고 있다면 어떻게 해야 할까요?

바로 이런 경우 차트에 드릴다운이 필요합니다. 드릴다운은 플롯과 관련된 추가 데이터가 포함된 새 하위 차트를 열기 위해 원본 또는 부모 차트에서 개별 데이터 플롯을 클릭하는 경우입니다. 이러한 추가/하위 데이터는 요구 사항에 따라 요구 시 API/데이터베이스에서 가져올 수 있습니다. 충분히 큰 데이터 집합을 사용하면 끝없는 수준의 드릴다운을 만들 수 있습니다.

이 블로그에서는 ComponentOne WPF FlexChart를 사용하여 비동기 드릴다운을 구현하는 방법을 설명합니다.

드릴다운

이번 사용 사례에서는 거래소에 등록된 화폐와 가격 차트로 드릴다운하는 암호화폐 거래소를 사용합니다.


데이터 소스 만들기

가장 먼저 거래, 화폐 및 가격 데이터를 나타낼 몇 가지 구조를 만듭니다. 따라서 동일하게 다음 클래스를 사용합니다.

public class CryptoExchange
{
     public int Id { get; set; }
     public string ExchangeName { get; set; }
     public int ListedCurrencies { get; set; }
}

public class CryptoCurrency
{
     public int Id { get; set; }
     public int ExchangeId { get; set; }
     public string CurrencyName { get; set; }
     public string Symbol { get; set; }
     public double CurrentPrice { get; set; }
}

public class PriceData
{
     public int Id { get; set; }
     public int CurrencyId { get; set; }
     public double High { get; set; }
     public double Low { get; set; }
     public double Open { get; set; }
     public double Close { get; set; }
     public DateTime Date { get; set; }
}    


거래, 화폐 및 가격 데이터를 저장/가져오기 위해 다음 DataService 클래스를 사용합니다. 요컨대, 이 클래스는 드릴다운 중 각 데이터를 가져오는 REST API를 모방합니다.

public class DataService
{
        public Task<IEnumerable<CryptoExchange>> FetchTop5CryptoExchanges() { }

        public async Task<IEnumerable<CryptoCurrency>> FetchTop4CryptoCurrencies(int exchangeId) { }
    
        public async Task<IEnumerable<PriceData>> FetchMonthlyPriceData(int currencyId) { }
    
        public async Task<IEnumerable<PriceData>> FetchWeeklyPriceData(int currencyId, int month) { }

        public async Task<IEnumerable<PriceData>> FetchDailyPriceData(int currencyId, int month, int week) { }
}


비동기식 드릴다운 관리자 만들기

이제 데이터 소스를 사용할 준비가 되었습니다. FlexChart를 사용하여 드릴다운을 수행하도록 허용하는 드릴다운 관리자를 구현합니다.

public interface IDrillDownManager
{
        /// Fires on drill down.
        event EventHandler<DrillEventArgs> DrilledDown;
 
        /// Fires on drill up.
        event EventHandler<DrillEventArgs> DrilledUp;
        
        // Gets the Drill depth (Number of steps).
        int Depth { get; }
        
        // Gets the current drilled level.
        int CurrentLevel { get; }
        
        // Gets the path that has been navigated/drilled.
        IEnumerable<StepResult> DrilledPath { get; }

        // Registers a drill down step which will be executed in the order they are added.
        void AddDrillDownStep(IDrillDownStep step);
        
        // Drill down one level.
        Task DrillDown(Point point);
        
        // Drill up one level.
        Task DrillUp();
        
        // Drills to specific path.
        Task DrillToPath(StepResult path);
        
        // Resets the drill level and clears the drilling history.
        void Reset();
}


위 코드에서 볼 수 있는 것처럼 AddDrillDownStep이라는 메서드가 있습니다.

public void AddDrillDownStep(IDrillDownStep step)
{
       _drillDownSteps.Add(step);
}


이 메서드를 사용하면 드릴다운 관리자로 여러 드릴다운 스텝을 등록할 수 있습니다(IDrillDownStep 구현). 이러한 스텝은 등록된 순서대로 실행됩니다. 드릴다운 스텝에 대해서는 이 블로그의 뒷부분에서 다룰 것입니다.

이제 가장 중요한 부분을 살펴보면, IDrillDownManager의 DrillDown 메서드를 사용하여 FlexChart에서 비동기식으로 드릴다운합니다.

public virtual async Task DrillDown(Point point)
{
       // perform hittest on chart
       var hitTest = _flexChart.HitTest(point);

       if (CanDrillDown(hitTest))
       {
             _currentLevel++;
             var drillDownStep = _drillDownSteps[_currentLevel];
             var result = await drillDownStep.Execute(hitTest); // execute step

             // add to history 
            _drillDownHistory.Push(new DrillInfo()
             {
                  HitTestInfo = hitTest,
                  StepPerformed = drillDownStep,
             });
             
              _drilledPath.Add(result);
              OnDrilledDown(new DrillEventArgs() { Level = _currentLevel });
       }
}

protected bool CanDrillDown(HitTestInfo hitTest)
{
        if (_drillDownSteps.Count == 0)
              return false;

        return _currentLevel < Depth && _drillDownSteps[_currentLevel + 1].CanExecute(hitTest);
}


위 코드에서는 IDrillDownStep의 CanExecute 메서드를 사용하여 드릴다운이 허용되는지 여부를 기본적으로 확인하는 CanDrillDown 메서드를 확인할 수 있습니다. 드릴다운이 허용되면 드릴다운 스텝이 실행되어 드릴업 작업에 대한 기록(드릴된 스텝)을 포함한 스택에 추가됩니다.

참고: IDrillDownStep의 CanExecute 메서드는 몇 가지 조건을 기준으로 FlexChart 드릴다운을 허용/금지하는 로직을 포함합니다. 예를 들어, 데이터 요소에서 5픽셀 이내의 거래에서 마우스를 클릭한 경우에만 드릴다운합니다.

마찬가지로, 기록 스택에 저장된 스텝을 실행하여 드릴업 작업을 구현할 수 있습니다. 그러나 이 블로그에서는 간단하게 설명하기 위해 DrillUp 메서드에 대한 코드 조각은 포함하지 않았습니다. 전체 구현 코드는 샘플을 참조하세요.


드릴다운 스텝 만들기

이제 드릴다운 스텝이 IDrillDownStep 인터페이스에서 구현된다는 내용을 이해했습니다. 이 인터페이스의 구현에는 다른 드릴 수준에서 받은 입력을 바탕으로 FlexChart를 구성하는 로직이 포함됩니다.

public interface IDrillDownStep
{
       /// Gets whether this step can execute or not.
       bool CanExecute(HitTestInfo hitTest);
​
       /// Executes the step.
       Task<StepResult> Execute(HitTestInfo hitTest);
}


이 블로그에서 언급한 것처럼 가상화폐 거래소를 사용하여 거래소의 등록 화폐 및 가격 차트를 드릴다운할 것입니다.

사용 사례에 따라 다음 단계를 수행해야 합니다.

  1. 가상화폐 거래소에 등록된 상위 5개 화폐의 세로 막대형 차트를 표시합니다.

  2. 1단계에서 선택한 화폐의 월별 캔들 차트를 표시합니다.

  3. 2단계에서 선택한 월 캔들의 주별 캔들 차트를 표시합니다.

  4. 3단계에서 선택한 주 캔들의 일별 캔들 차트를 표시합니다.

첫 번째 드릴다운 스텝을 만드는 것부터 시작해 보겠습니다. 즉, 거래소에 등록된 상위 4개 화폐를 표시해 보겠습니다.

public class ExchangeTop4CurrenciesStep : IDrillDownStep
{
        private DataService _dataService;

        public ExchangeTop4CurrenciesStep(DataService dataService)
        {
            _dataService = dataService;
        }

        public bool CanExecute(HitTestInfo hitTest)
        {
            // hittest object recieved from drill down manager
            return hitTest != null && 
                hitTest.Distance < 5 &&
                hitTest.ChartElement == ChartElement.PlotArea && 
                hitTest.Series != null &&
                hitTest.Item is CryptoExchange;
        }

        public async Task<StepResult> Execute(HitTestInfo hitTest)
        {
            var exchange = hitTest.Item as CryptoExchange;
            var currencies = await _dataService.FetchTop4CryptoCurrencies(exchange.Id);
            var chart = hitTest.Series.Chart as FlexChart;
            
            // resets chart 
            Helpers.ResetChart(chart);

            chart.ItemsSource = currencies.ToList();
            chart.Header = string.Format(StringResources.Exchange, exchange.ExchangeName);

            chart.DataLabel.Position = LabelPosition.Top;
            chart.DataLabel.Content = "{value}";
            chart.ToolTipContent = "Currency : {CurrencyName}\nSymbol : {Symbol}\nCurrent Price : {CurrentPrice}";

            // series configuration
            chart.Series.Clear();
            chart.Series.Add(new Series()
            {
                Binding = "CurrentPrice",
                BindingX = "CurrencyName"
            });

            // axis configuration
            chart.AxisX.Title = "Crypto Currencies";
            chart.AxisY.Title = "Current Price";
            chart.AxisY.Format = "C";
            chart.AxisX.TitleStyle = chart.HeaderStyle = chart.AxisY.TitleStyle = Helpers.AxisStyle;
            return new StepResult() { Value = exchange.ExchangeName };
        }
}


Execute 메서드 내에서 거래소의 상위 5개 암호화폐를 가져오는 데 사용되는 DataService 클래스를 이 스텝에 주입했습니다. 나중에 FlexChart의 ItemsSource, Series, Axis 등의 속성을 구성했습니다.

위 코드에서 이 StepResult가 무엇을 반환하는지 궁금할 수 있습니다. StepResult는 실행된 각 스텝에 대한 고유한 식별자 역할을 합니다.

이 경우에는 IDrillDownManager의 DrilledPath 속성 및 DrillToPath 메서드가 사용되었습니다. DrilledPath 속성은 실행될 때 등록된 스텝에서 반환되는 모든 StepResult를 저장합니다. 따라서 인스턴스를 IDrillDownManager의 DrillToPath 메서드에 전달하여 드릴다운된 특정 스텝으로 이동할 수 있습니다.

참고: 각 스텝은 StepResult의 새 인스턴스를 반환해야 합니다.

마찬가지로, 위에서 언급한 접근 방식에 따라 다른 스텝 3개를 만들 수 있습니다. (코드는 첨부된 샘플을 참조하세요.)


FlexChart와 드릴다운 관리자 통합

드릴다운 관리자 및 스텝을 사용할 준비가 되었으며 이제 FlexChart와 통합할 차례입니다. FlexChart가 포함된 프로젝트를 이미 만들었다고 가정해 보겠습니다. 이제 FlexChart의 초기 보기를 구성합니다. 예를 들어, 이 경우에는 다음과 같이 가상화폐 거래소의 상위 5개 화폐를 표시하는 세로 막대형 차트를 표시합니다.

var exchanges = await _dataService.FetchTop5CryptoExchanges();
chart.ItemsSource = exchanges.ToList();
chart.Header = "Top 5 Crypto Currency Exchanges";
​
chart.DataLabel.Position = LabelPosition.Top;
chart.DataLabel.Content = "{value}";
chart.ToolTipContent = "Listed Currencies : {value}";
​
// series configuration
chart.Series.Clear();
chart.Series.Add(new Series()
{
     Binding = "ListedCurrencies",
     BindingX = "ExchangeName"
});
​
// axis configuration
chart.AxisX.Title = "Crypto Exchanges";
chart.AxisY.Title = "Listed Currencies";
chart.AxisX.TitleStyle = chart.HeaderStyle = chart.AxisY.TitleStyle = Helpers.AxisStyle;
chart.AxisY.AxisLine = true;


그 결과는 다음과 같습니다.

img


완료하면 다음과 같이 드릴다운 관리자를 사용하여 드릴다운 스텝을 등록합니다.

_drillDownManager = new AsyncDrillDownManager(flexChart);
​
// register drill down steps
_drillDownManager.AddDrillDownStep(new ExchangeTop4CurrenciesStep(_dataService));
_drillDownManager.AddDrillDownStep(new MonthlyPriceChartStep(_dataService));
_drillDownManager.AddDrillDownStep(new WeeklyPriceChartStep(_dataService));
_drillDownManager.AddDrillDownStep(new DailyPriceChartStep(_dataService));


이제 드릴다운에 필요한 항목을 모두 설정했습니다. 남아 있는 유일한 단계는 FlexChart의 마우스 클릭 이벤트로 드릴다운 관리자를 사용하는 것입니다.

FlexChart의 MouseLeftButtonDown 내에서 IDrillDownManager의 DrillDown 메서드를 사용할 수 있도록 마우스 왼쪽 단추를 클릭하여 드릴다운합니다.

private async void OnFlexChartMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
     await _drillDownManager.DrillDown(e.GetPosition(flexChart));
}


마찬가지로, 드릴업을 위해 다음과 같이 FlexChart의 MouseRightButtonDown 이벤트를 사용할 수 있도록 마우스 오른쪽 버튼을 클릭합니다.

private async void OnFlexChartMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
     await _drillDownManager.DrillUp();
}


이제 완성입니다! FlexChart를 사용하여 비동기 드릴다운을 구현했습니다.

드릴다운





지금 바로 ComponentOne을 다운로드하여 직접 테스트해보세요!

 
  • 페이스북으로 공유
  • 트위터로  공유
  • 링크 복사
  • 카카오톡으로 보내기

댓글목록

등록된 댓글이 없습니다.

메시어스 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기

태그1

메시어스 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기
이메일 : sales-kor@mescius.com | 전화 : 1670-0583 | 경기도 과천시 과천대로 7길 33, 디테크타워 B동 1107호 메시어스(주) 대표자 : 허경명 | 사업자등록번호 : 123-84-00981 | 통신판매업신고번호 : 2013-경기안양-00331 ⓒ 2024 MESCIUS inc. All rights reserved.