まだ関連性があるかどうかはわかりませんが、セル テンプレート セレクターを使用して個々のセルのスタイルを設定する方法を見つけました。セルの適切な DataContext を取得するために ContentPresenter のコンテンツをいじる必要があるため (セル テンプレート内の実際のセル項目にバインドできるようにするため)、少しハックです。
public class DataMatrixCellTemplateSelectorWrapper : DataTemplateSelector
{
private readonly DataTemplateSelector _ActualSelector;
private readonly string _ColumnName;
private Dictionary<string, object> _OriginalRow;
public DataMatrixCellTemplateSelectorWrapper(DataTemplateSelector actualSelector, string columnName)
{
_ActualSelector = actualSelector;
_ColumnName = columnName;
}
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
// The item is basically the Content of the ContentPresenter.
// In the DataMatrix binding case that is the dictionary containing the cell objects.
// In order to be able to select a template based on the actual cell object and also
// be able to bind to that object within the template we need to set the DataContext
// of the template to the actual cell object. However after the template is selected
// the ContentPresenter will set the DataContext of the template to the presenters
// content.
// So in order to achieve what we want, we remember the original DataContext and then
// change the ContentPresenter content to the actual cell object.
// Therefor we need to remember the orginal DataContext otherwise in subsequent calls
// we would get the first cell object.
// remember old data context
if (item is Dictionary<string, object>)
{
_OriginalRow = item as Dictionary<string, object>;
}
if (_OriginalRow == null)
return null;
// get the actual cell object
var obj = _OriginalRow[_ColumnName];
// select the template based on the cell object
var template = _ActualSelector.SelectTemplate(obj, container);
// find the presenter and change the content to the cell object so that it will become
// the data context of the template
var presenter = WpfUtils.GetFirstParentForChild<ContentPresenter>(container);
if (presenter != null)
{
presenter.Content = obj;
}
return template;
}
}
注: 行が辞書 (ColumnName -> Cell Object) になるように、CodeProject の記事から DataMatrix を変更しました。
このソリューションが何かを壊さない、または将来の .Net リリースで壊れないことを保証することはできません。これは、ContentPresenter がテンプレートを選択した後に DataContext を独自のコンテンツに設定するという事実に依存しています。(これらの場合、リフレクターは非常に役立ちます:))
GridColumns を作成するときは、次のようにします。
var column = new GridViewColumn
{
Header = col.Name,
HeaderTemplate = gridView.ColumnHeaderTemplate
};
if (listView.CellTemplateSelector != null)
{
column.CellTemplateSelector = new DataMatrixCellTemplateSelectorWrapper(listView.CellTemplateSelector, col.Name);
}
else
{
column.DisplayMemberBinding = new Binding(string.Format("[{0}]", col.Name));
}
gridView.Columns.Add(column);
注: xaml でバインドできる CellTemplateSelector プロパティを持つように ListView を拡張しました。
@Edit 15/03/2011: 私は、小さなデモ プロジェクトが添付された小さな記事を書きました: http://codesilence.wordpress.com/2011/03/15/listview-with-dynamic-columns/