views:

3305

answers:

2

Hi all,

Couldn't find an answer to this one.

I have a WPF ListView control that can contain varying number of columns. For example, it can display customer data, displaying columns Id, Name, Email etc, or it can contain products, displaying ID, Name, Price, NumberInStock, Manufacturer, well, you get the idea: varying number of columns, varying names.

What I want to do, is for certain columns to display the data differently. For example, instead of printing 'Yes' or 'No' as the value of the column NumberInStock, I want to display a neat image.

If I'd have a fixed amount of columns, with fixed names to bind to, I kinda see how this is easy. Just define a DataTemplate for that particular column and I'd use that to define the view of my column. However, I can't see how to do it in my situation.

I am very new to WPF, so excuse me if my approach is bad :-) In my XAML, I have defined a ListView control, which is pretty much empty. In my code behind, I use:

    // 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);
        }

Ok, I'm sure this could be done a bit prettier (if you have any advice, please!) but the biggest problem is that I can't see any difference in the column. It just displays the text value of the 'NumberInStock' column. My DataTemplate is defined in the 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>

Of course, I would still have to add the functionality that it would display a 'yes' or 'no' image depending on the value of NumberInStock, but that is step 2 really. I would be happy to see an image and a red border in my ListView!

Thanks in advance, Razzie

A: 

I think the problem is that the string that you're passing to FindResource() doesn't match the key of the resource that you defined in the XAML. Try passing "NumberInStock" instead and see if that works.

Andy
Sharp! Unfortunately, it was merely a copy-paste-edit-for-question error on my side. It points to the correct key in my code. Moreover, FindResource(string) throws an exception when the key is not found. Thanks anyway!
Razzie
+2  A: 

This tripped me up for a while.

DisplayMemberBinding and CellTemplate are mutually exclusive. Specifying a DisplayMemberBinding causes the CellTemplate to be ignored.

From MSDN:

The following properties are all used to define the content and style of a column cell, and are listed here in their order of precedence, from highest to lowest:

* DisplayMemberBinding
* CellTemplate
* CellTemplateSelector

Also see a C# Disciples post about this.

TroyMclure
Thanks, that looks indeed like the problem. I already edited my code though to use a DataGrid control that comes with SP1. It may be more suitable in my situation anyway. But this is definately the right solution. Many thanks!
Razzie