WPF - 为通过程序添加的GridViewColumns设置DataTemplate

5

找不到答案。

我有一个WPF ListView控件,可以包含不同数量的列。例如,它可以显示客户数据,显示Id、Name、Email等列,或者它可以包含产品,显示ID、Name、Price、NumberInStock、Manufacturer等列,你懂的:列数和名称各不相同。

我的目标是让某些列以不同的方式显示数据。例如,我想在NumberInStock列中显示一个漂亮的图像,而不是打印'Yes'或'No'。

如果我有固定数量的列,并且有固定的名称进行绑定,我可以很容易地做到这一点。只需为该特定列定义一个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”列的文本值。我的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的值显示“是”或“否”的图像,但这实际上是第二步。 我很高兴在我的ListView中看到一个图像和红色边框!
提前致谢, Razzie
3个回答

10

这让我困扰了一段时间。

DisplayMemberBindingCellTemplate 是互斥的。指定 DisplayMemberBinding 会忽略 CellTemplate

来自 MSDN

以下属性都用于定义列单元格的内容和样式,并按优先顺序列在此处,从最高到最低:

* DisplayMemberBinding
* CellTemplate
* CellTemplateSelector

还可以看看关于这个的 C# Disciples的帖子


谢谢,看起来确实是问题所在。虽然我已经编辑了我的代码,使用了一个SP1附带的DataGrid控件。这可能更适合我的情况。但这绝对是正确的解决方案。非常感谢! - Razzie

3
这是插入图片最简单的方法。
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;

1
一些更详细的说明会很有用,但这指引我找到了正确答案(对我来说)。简而言之:这将为列生成内容创建器,因此每行都会调用工厂来生成工厂定义的控件。 谢谢.. +1 - Jeroen van Langen
这种方式对我有效。注意:我的绑定是到一个子对象属性的属性,所以它看起来像这样:Binding newBinding = new Binding("ChildProp.SubProp"); newBinding.Converter = new MyConverter(); - Jesse Chisholm

0

我认为问题在于您传递给FindResource()的字符串与您在XAML中定义的资源键不匹配。尝试传递"NumberInStock",看看是否有效。


太棒了!不幸的是,这只是我在复制粘贴编辑问题时犯的错误。它在我的代码中指向正确的键。此外,当找不到该键时,FindResource(string)会抛出异常。无论如何,还是谢谢! - Razzie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接