C#
WPF
VisualStudio
OxyPlot

WPF OxyPlotをDataGridと連動させる

More than 1 year has passed since last update.

グラフが書けるライブラリ「OxyPlot」でトラッカーを動かした時にDataGridも連動させたかったのでやってみた
こんな感じで動いてくれる

DataGridLinkeOxyPlotSample.gif

※OxyPlotについてはドキュメントみればなんとなくわかると思うのでここでは使い方とかは解説しない
需要があればざっくりの使い方の記事書くかも

やりかた

前提として、同じデータのコレクションがOxyPlotとDataGirdにバインドされていること

    public class PointData
    {
        public double _X{ get; set; }
        public double _YA { get; set; }
        public double _YB{ get; set; }
        public double _YC{ get; set; }
        public double _YD{ get; set; }
        public double _YE{ get; set; }
        public double _YF{ get; set; }
    }

サンプルデータはこんな感じにしている
そんで

    public class OxyPlot_Behavior : Behavior<Plot>
    {
        #region targetDataGridプロパティ
        public DataGrid targetDataGrid
        {
            get { return (DataGrid)GetValue(targetDataGridProperty); }
            set { SetValue(targetDataGridProperty, value); }
        }
        // Using a DependencyProperty as the backing store for targetDataGrid.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty targetDataGridProperty =
            DependencyProperty.Register("targetDataGrid", typeof(DataGrid), typeof(OxyPlot_Behavior), new PropertyMetadata(null));
        #endregion


        protected override void OnAttached()
        {
            AssociatedObject.ActualModel.TrackerChanged += ActualModel_TrackerChanged;
        }

        protected override void OnDetaching()
        {
            AssociatedObject.ActualModel.TrackerChanged -= ActualModel_TrackerChanged;
        }

        private void ActualModel_TrackerChanged(object sender, TrackerEventArgs e)
        {
            if (e.HitResult == null) return;
            var res = e.HitResult.Item as PointData;
            targetDataGrid.Focus();
            targetDataGrid.SelectedIndex = targetDataGrid.Items.IndexOf(res);
            targetDataGrid.CurrentCell = new DataGridCellInfo(res, targetDataGrid.Columns[0]);
        }
    }

こんな感じのBehaviorを作ってDataGridをバインドするだけ
ポイントは、
AssociatedObject.ActualModelのTrackerChangedイベントに処理を書くこと
実際にやってることはイベントから取れるItemの行をDataGrid内から探して、それを選択して移動してるだけ
Viewはこんな感じでバインドする

<i:Interaction.Behaviors>
    <be:OxyPlot_Behavior targetDataGrid="{Binding ElementName=DataGrid, Mode=OneWay}"/>
</i:Interaction.Behaviors>