[LiveCharts2] ChartEntityMetaData

追追追,找出 ChartEntityMetaData 到底在幹甚麼。

IChartEntity interface 的內容很簡單,就兩個屬性而已。

public interface IChartEntity
{
    ChartEntityMetaData? MetaData { get; set; }
    
    Coordinate Coordinate { get; set; }
}

Coordinate 和座標相關這件事情比較好懂一點,讓我有點不好理解的是 MetaData 這個屬性,從上面的程式碼內容可以看出來它的型別是 ChartEntityMetaData  。

ChartEntityMetaData class

這個類別有幾個有趣的地方,第一個是 EntityIndex 屬性,說明裡面講的是這個執行個體在集合中的位置,事實上這個變動會發生於渲染畫面時期,並非是在加進集合的時候;第二個有趣的地方是它的建構式會傳一個 Action<int> 委派,這個委派在類別內部被呼叫的時機是當 EntityIndex 屬性值改變的時候。

 public int EntityIndex
 {
     get
     {
         return _entityIndex;
     }
     set
     {
         if (value != _entityIndex)
         {
             _entityIndex = value;
             _entityIndexChangedCallback?.Invoke(value);
         }
     }
 }

從程式碼可以看出來當 EntityIndex 屬性值改變會引發委派執行,並且將新的 index 值作為引數。

玩看看

我寫一個測試範例想找出 EntityIndex 屬性變動的時機,完整範例參考此處。以下列出主要的段落:

 public ICommand ClickCommand
 {
     get
     {
         return new RelayCommand(async x =>
         {
             People = new ObservableCollection<PersonViewModel>()
             {
                 new PersonViewModel { Name = "A", Score = 98 },
                 new PersonViewModel { Name = "B", Score = 68 },
                 new PersonViewModel { Name = "C", Score = 77 },
             };
             await Display(0);
             var Points = new ColumnSeries<PersonViewModel>();
             Points.Values = People;
             await Display(1);
             var Series = new ObservableCollection<ISeries>();
             Series.Add(Points);
             await Display(2);
             var XAxes = new ObservableCollection<Axis>();
             XAxes.Add(new Axis { Labels = new ObservableCollection<string>(People.Select(x => x.Name)) });
             await Display(3);
             var YAxes = new ObservableCollection<Axis>();
             YAxes.Add(new Axis { Labeler = value => $"{value} S", });
             await Display(4);
             var chart = new CartesianChart()
             {
                 Height = 150,
                 Series = Series,
                 XAxes = XAxes,
                 YAxes = YAxes,
                 Background = new SolidColorBrush(Colors.Yellow)
             };
             await Display(5);
             panel.Children.Add(chart);
             await Display(6);
             async Task Display(int testIndex)
             {
                 await Task.Delay(80);
                 Debug.WriteLine($"({testIndex}) {string.Join(",", People.Select(x => x.MetaData.EntityIndex))}");
             }
         });
     }
 }

之所以需要 Task Delay 是因為 UI Thread 和 Rendering Thread 是分開的,如果不 Delay 的話,渲染還沒完成前可能就會跑到 Debug.WriteLine,這樣就測不出結果了。

執行輸出大致是以下這樣,在 (6) 的時候已經渲染完成才會發現 EntityIndex 屬性值改變了 :

(0) -1,-1,-1
(1) -1,-1,-1
(2) -1,-1,-1
(3) -1,-1,-1
(4) -1,-1,-1
(5) -1,-1,-1
(6) 0,1,2

前一個 Sample004 因為還沒解說這個 MetaData 的內容,所以近乎硬幹的在 PersonViewModel 裡加入了一個 Index 屬性,現在我們大致了解這東西怎麼用了,下一篇應用這個特性來改造 Sample004。