WPF - установка DataTemplate для программно добавленных столбцов GridViewColumns

Не нашел ответа на этот вопрос.

У меня есть элемент управления WPF ListView, который может содержать различное количество столбцов. Например, он может отображать данные клиента, отображая столбцы Id, Name, Email и т. Д., Или он может содержать продукты, отображая идентификатор, имя, цену, NumberInStock, Manufacturer, ну, вы понимаете: разное количество столбцов, разные имена.

Я хочу сделать так, чтобы в некоторых столбцах данные отображались по-разному. Например, вместо того, чтобы печатать «Да» или «Нет» в качестве значения столбца NumberInStock, я хочу отобразить аккуратное изображение.

Если бы у меня было фиксированное количество столбцов с фиксированными именами для привязки, я бы понял, насколько это просто. Просто определите DataTemplate для этого конкретного столбца, и я буду использовать его для определения представления моего столбца. Однако я не вижу, как это сделать в моей ситуации.

Я новичок в WPF, так что извините, если мой подход плохой :-) В моем XAML я определил элемент управления ListView, который практически пуст. В моем коде позади я использую:

    // get all columns from my objects (which can be either a Customer of Product)
    foreach (string columnName in MyObject.Columns)
        {
          GridViewColumn column = new GridViewColumn();
          // Bind to a property of my object
          column.DisplayMemberBinding = new Binding("MyObject." + columnName);
          column.Header = columnName;
          column.Width = 50;
          // If the columnname is number of stock, set the template to a specific datatemplate defined in XAML
          if (columnName == "NumberInStock")
            column.CellTemplate = (DataTemplate)FindResource("numberInStockImageTemplate");
          explorerGrid.Columns.Add(column);
        }

Хорошо, я уверен, что это можно было бы сделать немного красивее (если у вас есть какие-либо советы, пожалуйста!), Но самая большая проблема в том, что я не вижу никакой разницы в столбце. Он просто отображает текстовое значение столбца NumberInStock. My DataTemplate определен в XAML:

<Window.Resources>
<DataTemplate x:Name="NumberInStock" x:Key="NumberInStock">
      <Border BorderBrush="Red" BorderThickness="2.0">
        <DockPanel>
          <Image Width="24" Height="24" Margin="3,0" Source="..\Images\instock.png" />
        </DockPanel>
      </Border>
</DataTemplate>
</Window.Resources>

Конечно, мне все равно придется добавить функциональность, которая будет отображать изображение «да» или «нет» в зависимости от значения NumberInStock, но на самом деле это шаг 2. Я был бы рад увидеть изображение и красную рамку в моем ListView!

Заранее спасибо, Раззи

Ответов (3)

Решение

Это меня на время сбило с толку.

DisplayMemberBinding и CellTemplate являются взаимоисключающими. Указание DisplayMemberBinding приводит CellTemplate к игнорированию.

Из MSDN :

Следующие свойства используются для определения содержимого и стиля ячейки столбца и перечислены здесь в порядке их приоритета от наивысшего к низшему:

* DisplayMemberBinding
* CellTemplate
* CellTemplateSelector

Также см. Сообщение C# Disciples об этом.

Я думаю, проблема в том, что строка, которую вы передаете FindResource(), не соответствует ключу ресурса, который вы определили в XAML. Попробуйте "NumberInStock" вместо этого пройти и посмотрите, работает ли это.

Это самый простой способ вставить картинку

GridViewColumn column = new GridViewColumn { Header = "IM" };            
DataTemplate template = new DataTemplate();

FrameworkElementFactory factory  =  new FrameworkElementFactory(typeof(Grid));
template.VisualTree = factory;
FrameworkElementFactory imgFactory  =  new FrameworkElementFactory(typeof(Image));

Binding newBinding  =  new Binding("IMG");
imgFactory.SetBinding(Image.SourceProperty,newBinding);
imgFactory.SetValue(Image.WidthProperty,15.0);
imgFactory.SetValue(Image.HeightProperty, 15.0);

factory.AppendChild(imgFactory);
column.CellTemplate = template;
view.Columns.Add(column);

ListViewMain.View = view;