Не уверен, что это все еще актуально, но я нашел способ стилизации отдельных ячеек с помощью селектора шаблонов ячеек. Это немного неуместно, потому что вам приходится работать с Content of ContentPresenter, чтобы получить правильный DataContext для ячейки (чтобы вы могли привязаться к фактическому элементу ячейки в шаблоне ячейки):
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;
}
}
Примечание: я изменил DataMatrix из статьи CodeProject, чтобы строки были словарями (ColumnName -> Cell Object).
Я не могу гарантировать, что это решение не сломает что-либо или не сломается в будущем выпуске .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);
Примечание: я расширил ListView, чтобы у него было свойство CellTemplateSelector, к которому можно привязаться в xaml
@ Изменить 15/03/2011:
Я написал небольшую статью, к которой прикреплен небольшой демонстрационный проект: http://codesilence.wordpress.com/2011/03/15/listview-with-dynamic-columns/