xamGrid のカスタム列の作成

0 ユーザーが評価
この投稿には確認済みの回答があります。 0 返信 | 1 サポーター

トップ 10 投稿者 
女性
投稿 22
IG Employee

元記事 (英語): Devin Rader - http://forums.infragistics.com/blogs/devin_rader/archive/2010/07/08/creating-custom-columns-for-xamgrid.aspx

 

xamGrid のカスタム列の作成

 

インフラジスティックス xamGrid のデザインの過程において、開発者が簡単にカスタム列の型を作成し、コントロールを拡張する方法を提供することを決定しました。グリッドの最初のバージョンでは、必要な列タイプをすべて提供できないことでした。開発者が将来にアプリケーションで使用する列タイプも知らないことです。現在のグリッドは 7 つの列タイプを含みますが、カスタム列タイプの作成を有効にする API があります。

この記事では、xamGrid のカスタム列を作成するために、グリッドの API を使用する方法を 2 つの例を使って紹介します。1 つは Button コントロールを含む編集が無効な列です。2 つ目は ComboBox をエディター コントロールとして使用する編集可能な列です。記事で使用するソース コードはページの下部にダウンロード リンクがあります。

カスタム列の設定

カスタム列の作成で必要なクラスの基本アウトラインを設定します。このアウトラインは ButtonColumn に適用しますが、新しく列タイプを作成する場合も同じです。

まず行わなければならないことは、ColumnContentProviderBase クラスから派生するクラスを作成することです。ColumnContentProviderBase は、列のセルから UI コンテンツを取得するか、編集可能なセルの値を解決する必要があるときにグリッドが呼び出す仮想メソッドを公開します。ここではメソッド オーバーライドのみを実装します。後でカスタム列のメソッド ロジックを追加します。

  1. public class ButtonColumnContentProvider : ColumnContentProviderBase  
  2. {  
  3.     public override FrameworkElement   
  4.         ResolveDisplayElement(Cell cell, Binding cellBinding)  
  5.     {  
  6.         throw new NotImplementedException();  
  7.     }  
  8.   
  9.     protected override FrameworkElement ResolveEditorControl  
  10.         (Cell cell, object editorValue, double availableWidth,   
  11.          double availableHeight, Binding editorBinding)  
  12.     {  
  13.         throw new NotImplementedException();  
  14.     }  
  15.   
  16.     public override object ResolveValueFromEditor(Cell cell)  
  17.     {  
  18.         throw new NotImplementedException();  
  19.     }  
  20. }  

次に、Column クラスから派生する他のクラスを追加する必要があります。Column (または EditableColumn) から派生されるクラスは、最終的にグリッドの Columns コレクションに追加されます。オーバーライドする必要のある Column クラスの GenerateContentProvider 仮想メソッドは Column と ControlContentProvider を接続します。

このメソッドを実装するには、コンテンツ プロバイダーのインスタンスを作成し、それを返します。

  1. public class ButtonColumn : Column  
  2. {  
  3.     protected override ColumnContentProviderBase GenerateContentProvider()  
  4.     {  
  5.         return new ButtonColumnContentProvider();  
  6.     }  
  7. }  

ButtonColumn の作成

基本アウトラインを設定したので、次に ButtonColumn のロジックの実装をします。ButtonColumn は列のセルに Button コントロールを追加して、Button のコンテンツに割り当てる、またはバインドが可能で、Button の行インデックスと行データを提供するフック可能な Click イベントを含みます。

列のパブリック プロパティとイベントの構成

列を作成するには、Button のコンテンツを提供するために ButtonColumn クラスに Content と ContentBinding 依存プロパティを追加します。最終的に ButtonColumn クラスはグリッドの Columns コレクションに追加するため、列の構成プロパティをこのクラスで公開する必要があります。

  1. public static readonly DependencyProperty ContentProperty =  
  2.     DependencyProperty.Register("Content", typeof(string),   
  3.         typeof(ButtonColumn),   
  4.         new PropertyMetadata(  
  5.             new PropertyChangedCallback(ContentChanged)));  
  6.   
  7. public string Content  
  8. {  
  9.     get { return (string)this.GetValue(ContentProperty); }  
  10.     set { this.SetValue(ContentProperty, value); }  
  11. }  
  12. private static void ContentChanged(DependencyObject obj,   
  13.                    DependencyPropertyChangedEventArgs e)  
  14. {  
  15.     ButtonColumn col = (ButtonColumn)obj;  
  16.     col.OnPropertyChanged("Content");  
  17. }  
  18.   
  19. public static readonly DependencyProperty ContentBindingProperty =   
  20.     DependencyProperty.Register("ContentBinding",   
  21.         typeof(Binding), typeof(ButtonColumn),   
  22.         new PropertyMetadata(  
  23.             new PropertyChangedCallback(ContentBindingChanged)));  
  24.   
  25. public Binding ContentBinding  
  26. {  
  27.     get { return (Binding)this.GetValue(ContentBindingProperty); }  
  28.     set { this.SetValue(ContentBindingProperty, value); }  
  29. }  
  30.   
  31. private static void ContentBindingChanged(DependencyObject obj,  
  32.     DependencyPropertyChangedEventArgs e)  
  33. {  
  34.     ButtonColumn col = (ButtonColumn)obj;  
  35.     col.OnPropertyChanged("ContentBinding");  
  36. }  

列の Button をクリックしたときに通知するために、ButtonColumn クラスに Click イベントを追加します。

  1. public event EventHandler<ButtonColumnClickEventArgs> Click;  
  2. protected internal void OnClick(ButtonColumnClickEventArgs e)  
  3. {  
  4.     if (Click != null)  
  5.     {  
  6.         this.Click(this, e);  
  7.     }  
  8. }  

Click イベントが標準の EventArgs オブジェクトの代わりに ButtonColumnClickEventArgs と呼ばれるカスタム イベント引数オブジェクトを返すことに注意してください。このカスタム オブジェクトはボタンの行インデックスと行データを提供します。

  1. public class ButtonColumnClickEventArgs : EventArgs  
  2. {  
  3.     int _index;  
  4.     object _data;  
  5.       
  6.     internal ButtonColumnClickEventArgs(int index, object data)  
  7.     {  
  8.         _index = index;  
  9.         _data = data;  
  10.     }  
  11.   
  12.     public int Index { get { return _index; } }  
  13.     public object Data { get { return _data; } }  
  14. }  

ButtonColumn を作成するための変更がもう 1 つあります。デフォルトでは Grid のすべての列の Key プロパティをグリッドの項目ソースの実際のプロパティに設定する必要があります。Key が項目ソースで見つからない場合、例外を発生します。ButtonColumn では意味がないため、列の Key が項目ソースで存在する制限を削除します。RequiresBoundDataKey プロパティをオーバーライドして False を返すと実装します。

  1. protected override bool RequiresBoundDataKey  
  2. {  
  3.     get  
  4.     {  
  5.         return false;  
  6.     }  
  7. }  

ButtonColumn クラスの変更が完了しました。コンテンツ プロバイダー クラスで Button を列のセルに挿入するロジックを追加します。 

列の表示要素の作成

列で Button を表示して Click イベントを発生するロジックを実装するには、最初に Button オブジェクトのインスタンスをコンストラクターで作成して、新しいイベント ハンドラー メソッドに Button のクリック イベントを処理する必要があります。

  1. Button _button;  
  2.   
  3. public ButtonColumnContentProvider()  
  4. {  
  5.     _button = new Button();  
  6.     _button.Click += new RoutedEventHandler(button_Click);  
  7. }  

グリッドで列のセルのコンテンツとして Button を使用するには、ResolveDisplayElement メソッドから Button を返します。

  1. public override FrameworkElement ResolveDisplayElement  
  2.     (Cell cell, Binding cellBinding)  
  3. {  
  4.     return _button;  
  5. }  

ResolveDisplayElement は、セルで新しい UI コンテンツを表示するときに、グリッドから呼び出されます。たとえば、グリッドが読み込むときに、10 行が表示可能で、ResolveDisplayElement は 10 回呼び出されます。グリッドの高さを変更しない場合は、ResolveDisplayElement が再び呼び出されることはありません。グリッドの高さが追加の 5 行を表示するために変更する場合、列で追加の 5 セルのコンテンツを作成するために ResolveDisplayElement が 5 回呼び出されます。 

ここで列をグリッドに追加した場合、Button が表示されますが、コンテンツがない場合にクリックしても何も起動されません。Button にコンテンツを追加するには、ButtonColumn で作成した Content と ContentBinding プロパティを使用するコードをコンテンツ プロバイダー クラスに追加します。以下のコードは、ResolveDisplayElement メソッドを変更する方法を紹介します。

  1. public override FrameworkElement ResolveDisplayElement  
  2.     (Infragistics.Silverlight.Controls.Cell cell,   
  3.      System.Windows.Data.Binding cellBinding)  
  4. {  
  5.     _column = (ButtonColumn)cell.Column;  
  6.   
  7.     Binding binding = new Binding(_column.Key);  
  8.     if (_column.Content == null)  
  9.     {  
  10.         binding.Mode = BindingMode.OneWay;  
  11.         if (_column.ContentBinding != null)  
  12.         {  
  13.             this._button.SetBinding(Button.ContentProperty,   
  14.                                     _column.ContentBinding);  
  15.         }  
  16.         else  
  17.         {  
  18.             this._button.SetBinding(Button.ContentProperty, binding);  
  19.         }  
  20.     }  
  21.     else  
  22.     {  
  23.         binding = new Binding("Content");  
  24.         binding.Source = _column;  
  25.         this._button.SetBinding(Button.ContentProperty, binding);  
  26.     }  
  27.   
  28.     return _button;  
  29. }  

Content プロパティが null 値かどうか、ContentBinding プロパティを使用するかどうかを確認します。ContentBinding プロパティが null 値の場合、列キーにバインドします。Content プロパティが null 値以外の場合、その値を使用します。

列のセルで Button がクリックされたときに、列の Click イベントを発生する必要があります。Click イベントで、クリックしたボタンを含む行のインデックスを含むカスタム イベント引数オブジェクトとその行のデータを返します。グリッドが UI 要素をリサイクルするため、イベント引数で正しいデータを確認する必要があります。このために、AdjustDisplayElement メソッドをオーバーライドします。使用頻度の低い ResolveDisplayElement とは異なり、レイアウト サイクルで測定が呼び出されるたびに、AdjustDisplayElement メソッドが呼び出されます。特定のセルのコントロールを変更するために、このメソッドは便利です。

クリック イベント引数で正しいデータを返すことを確認するには、AdjustDisplayElement メソッドでセル パラメーターをローカル メンバーに保存します。

  1. public override void AdjustDisplayElement(Infragistics.Controls.Grids.Cell cell)  
  2. {  
  3.     this._cell = cell;  
  4.   
  5.     base.AdjustDisplayElement(cell);  
  6. }  

ButtonColumnClickEventArgs の新しいインスタンスを作成するコードを追加して、列のパブリック Click イベントを以前作成したボタン クリック ハンドラーで発生することができます。

  1. void button_Click(object sender, RoutedEventArgs e)  
  2. {  
  3.     ButtonColumnClickEventArgs _clickeventargs =   
  4.         new ButtonColumnClickEventArgs(_cell.Row.Index, _cell.Row.Data);  
  5.     _column.OnClick(_clickeventargs);  
  6. }  

ButtonColumn の作成が完了しました。xamGrid で使用するには、グリッドの列コレクションに追加します。

  1. <igGrid:XamGrid x:Name="xamgrid1" Grid.Row="1">  
  2.     <igGrid:XamGrid.Columns>  
  3.         <igGrid:TextColumn Key="PropA" />  
  4.         <igcc:ButtonColumn Key="PropB"   
  5.             Click="ButtonColumn_Click" Content="OK"  />  
  6.     </igGrid:XamGrid.Columns>  
  7. </igGrid:XamGrid>  

以下の画像では、ボタン列が追加したグリッドを表示します。

列のボタンをクリックすると、ボタンの行インデックスと行のオブジェクト タイプを示す行を Textbox に追加します。

編集可能な ComboBoxColumn の作成

ComboBox コントロールを値エディターとして使用する編集可能な列を作成します。記事で説明した基本カスタム列フレームワークを再利用して、列クラスを少し変更します。Column から派生する代わりに、EditableColumn クラスから派生します。列が編集可能になり、グリッドで公開される標準セル編集イベントを使用できます。

  1. public class ComboBoxColumn : EditableColumn  
  2. {  
  3.     protected override ColumnContentProviderBase GenerateContentProvider()  
  4.     {  
  5.         return new ComboBoxColumnContentProvider();  
  6.     }  
  7. }  

ButtonColumn の作成と同じ手順を実行します。最初に、Column から公開するプロパティを設定します。次に、コンテンツ プロバイダー クラスで表示要素とエディター コントロールを設定します。

列プロパティの構成

ComboBoxColumn では、セル エディターとして使用される内部の ComboBox の設定と関連付けられます。ItemSource と DisplayMemberPath を使用します。ComboBox 項目の外観をカスタマイズするために、ItemsTemplate も使用します。

  1. public static readonly DependencyProperty ItemSourceProperty =   
  2.     DependencyProperty.Register("ItemSource",   
  3.         typeof(IEnumerable),   
  4.         typeof(ComboBoxColumn),   
  5.         new PropertyMetadata(  
  6.             new PropertyChangedCallback(ItemSourceChanged)));  
  7.   
  8. public IEnumerable ItemSource  
  9. {  
  10.     get { return (IEnumerable)this.GetValue(ItemSourceProperty); }  
  11.     set { this.SetValue(ItemSourceProperty, value); }  
  12. }  
  13.   
  14. private static void ItemSourceChanged(DependencyObject obj,   
  15.     DependencyPropertyChangedEventArgs e)  
  16. {  
  17.     ComboBoxColumn col = (ComboBoxColumn)obj;  
  18.     col.OnPropertyChanged("ItemSource");  
  19. }  
  20.   
  21. public static readonly DependencyProperty DisplayMemberPathProperty =   
  22.     DependencyProperty.Register("DisplayMemberPath",   
  23.         typeof(string),   
  24.         typeof(ComboBoxColumn),   
  25.         new PropertyMetadata(  
  26.             new PropertyChangedCallback(DisplayMemberPathChanged)));  
  27.   
  28. public string DisplayMemberPath  
  29. {  
  30.     get { return (string)this.GetValue(DisplayMemberPathProperty); }  
  31.     set { this.SetValue(DisplayMemberPathProperty, value); }  
  32. }  
  33.   
  34. private static void DisplayMemberPathChanged(DependencyObject obj,   
  35.     DependencyPropertyChangedEventArgs e)  
  36. {  
  37.     ComboBoxColumn col = (ComboBoxColumn)obj;  
  38.     col.OnPropertyChanged("DisplayMemberPath");  
  39. }  
  40.   
  41. public static readonly DependencyProperty ItemTemplateProperty =   
  42.     DependencyProperty.Register("ItemTemplate",   
  43.         typeof(DataTemplate),   
  44.         typeof(ComboBoxColumn),   
  45.         new PropertyMetadata(  
  46.             new PropertyChangedCallback(ItemTemplateChanged)));  
  47.   
  48. public string ItemTemplate  
  49. {  
  50.     get { return (string)this.GetValue(ItemTemplateProperty); }  
  51.     set { this.SetValue(ItemTemplateProperty, value); }  
  52. }  
  53.   
  54. private static void ItemTemplateChanged(DependencyObject obj,   
  55.     DependencyPropertyChangedEventArgs e)  
  56. {  
  57.     ComboBoxColumn col = (ComboBoxColumn)obj;  
  58.     col.OnPropertyChanged("ItemTemplate");  
  59. }  

列の構成が完了しました。コンテンツ プロバイダーに戻って、列の設定を完了しましょう。

列の表示要素とエディター コントロールの作成

ComboBoxColumn では、列の DisplayElement として TextBlock を使用し、コントロール エディターとして ComboBox を使用します。まず、このコントロールのインスタンスを作成して、適切なメソッドから返します。

  1. public class ComboBoxColumnContentProvider : ColumnContentProviderBase  
  2. {  
  3.     TextBlock _tb;  
  4.     ComboBox _combobox;  
  5.   
  6.     public ComboBoxColumnContentProvider()  
  7.     {  
  8.         _tb = new TextBlock();  
  9.         _combobox = new ComboBox();  
  10.     }  
  11.   
  12.     public override FrameworkElement ResolveDisplayElement  
  13.         (Infragistics.Silverlight.Controls.Cell cell,   
  14.          System.Windows.Data.Binding cellBinding)  
  15.     {  
  16.         return _tb;  
  17.     }  
  18.   
  19.     protected override FrameworkElement ResolveEditorControl  
  20.         (Infragistics.Silverlight.Controls.Cell cell,   
  21.          object editorValue, double availableWidth,   
  22.          double availableHeight, System.Windows.Data.Binding editorBinding)  
  23.     {  
  24.         return this._combobox;  
  25.     }  
  26.   
  27.     public override object ResolveValueFromEditor  
  28.         (Infragistics.Silverlight.Controls.Cell cell)  
  29.     {  
  30.         return null;  
  31.   
  32.     }  
  33. }  

ButtonColumn と同じように、Binding を使用して TextBlock をセル値にバインドする必要があります。

  1. public override FrameworkElement ResolveDisplayElement  
  2.     (Infragistics.Silverlight.Controls.Cell cell,   
  3.      System.Windows.Data.Binding cellBinding)  
  4. {  
  5.     ComboBoxColumn column = (ComboBoxColumn)cell.Column;  
  6.   
  7.     Binding textBinding = new Binding();  
  8.     textBinding.Source = cell.Row.Data;  
  9.   
  10.     if (column.DisplayMemberPath!=null)  
  11.         textBinding.Path =   
  12.             new PropertyPath(string.Format("{0}.{1}",column.Key,   
  13.                              column.DisplayMemberPath));  
  14.     else  
  15.         textBinding.Path = new PropertyPath(column.Key);  
  16.   
  17.     textBinding.Mode = BindingMode.TwoWay;  
  18.     this._tb.SetBinding(TextBlock.TextProperty, textBinding);  
  19.   
  20.     return _tb;  
  21. }  

列の DisplayMemberPath プロパティを設定したときに、Binding オブジェクトで列の Key と DisplayMemberPath を結合する PropertyPath を作成して、それを Binding オブジェクトの Path として設定します。パスを作成したら、Binding を TextBlock の Text プロパティに割り当てます。

表示要素が設定したため、ComboBox と ResolveEditorControl メソッドを使用して、この列の編集エクスペリエンスを作成します。表示エディターの設定と同じような手順です。エディター コントロールのインスタンスを作成して、セル データにバインドします。ComboBox がバインドしたコントロールのため、データ ソースに接続して、選択した項目のプロパティを設定する必要があります。

  1. ComboBoxColumn column = (ComboBoxColumn)cell.Column;  
  2.   
  3. this._combobox.SetValue(ComboBox.ItemsSourceProperty, column.ItemSource);  
  4. this._combobox.SetValue(ComboBox.DisplayMemberPathProperty,   
  5.                         column.DisplayMemberPath);  
  6.   
  7. Binding selectedItemBinding = new Binding();  
  8. selectedItemBinding.Source = cell.Row.Data;  
  9. selectedItemBinding.Path = new PropertyPath(column.Key);  
  10. selectedItemBinding.Mode = BindingMode.TwoWay;  
  11.   
  12. this._combobox.SetBinding(ComboBox.SelectedItemProperty, selectedItemBinding);  
  13.   
  14. this._combobox.Style = cell.EditorStyleResolved;  
  15.   
  16. return this._combobox;  

列の ItemSource と DisplayMemberPath プロパティから相対の ComboBox 列に値を割り当てます。次に、ComboBox の SelectedItem プロパティにセルの値をバインドするために selectedItemBinding と呼ばれる新しいバインディングを作成します。ここで、バインディングの Mode は TwoWay に設定されていることに注意してください。ComboBox の読み込み時に、デフォルトで正しい項目が選択されます。ComboBox の SelectedItem が変更した場合、ComboBox の SelectedItemChanged イベントを処理せずに、セル値を自動的に更新します。

最後に、コンテンツ プロバイダーの ResolveValueFromEditor メソッドを使用して ComboBox の選択した値をセル値として割り当てます。それには、そのメソッドから ComboBox の SelectedItem プロパティを返します。

  1. public override object ResolveValueFromEditor  
  2.     (Infragistics.Silverlight.Controls.Cell cell)  
  3. {  
  4.     return this._combobox.SelectedItem;  
  5. }  

グリッドの API を使用したカスタム ComboBoxEditor 列の作成が完了しました。この列をグリッドで読み込むと、以下の画像のように、セルが編集モードにあるときに、TextBlock で表示されるセル値が表示されます。セルを編集モードになるときに、バインドした値の ComboBox を表示して、デフォルトでセル値が選択されます。

 

まとめ

簡単にカスタム列タイプを作成して xamGrid を拡張できます。例のソース コードは下部にリンクされます。サンプルをコンパイルするには、NetAdvantage for Silverlight の最近のバージョンをインストールする必要があることに注意してください。以下は、ソース コードと NetAdvantage のダウンロードへのリンクです。

 

 

ページ 1 / 1 (1 項目) | RSS
Infragistics Japan
インフラジスティックス ジャパン