WPF DataGrid:CellEditingTemplate将多个数据组合到CellTemplate TextBox

时间:2012-06-06 07:19:58

标签: wpf datagrid combobox celltemplate celleditingtemplate

我用Google搜索,但运气非常有限。我有一个关于可编辑WPF DataGrid的问题;在CellEditingTemplate中显示了一个ComboBox,但在CellTemplate中显示了一个带有相应ComboBox值的TextBox。我的代码看起来像这样:

<DataGridTemplateColumn Header="Unit">
  <DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
      <ComboBox Name="comboBoxUnit" ItemsSource="{Binding ...}" SelectedValue="{Binding UnitId, ValidatesOnDataErrors=True}" SelectedValuePath="Id">
        <ComboBox.ItemTemplate>
          <DataTemplate>
            <StackPanel Orientation="Horizontal">
              <TextBlock Text="{Binding Id}" />
              <TextBlock Text=" " />
              <TextBlock Text="{Binding Name}" />
            </StackPanel>
          </DataTemplate>
        </ComboBox.ItemTemplate>
      </ComboBox>
    </DataTemplate>
  </DataGridTemplateColumn.CellEditingTemplate>
  <DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
      <TextBlock Text="<would like to have selected Unit's Id and Name here>"  />
    </DataTemplate>                                    
  </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

我怎样才能做到这一点?一个类中的单独属性(具有UnitId和UnitName属性)不是问题,我可以添加它,但是如何将它们绑定到ComboBox呢?我可以在CellTemplate中访问CellEditingTemplate ComboBox吗?看起来它们处于“不同的命名空间”,因为我可以用相同的名称命名控件......

任何想法,指针?提前致谢, DB

1 个答案:

答案 0 :(得分:3)

实现同样目标的最简单方法是使用DataGridComboBoxColumn

但是,在我目前的项目中,DataGridComboBoxColumn出现了很多问题,我们不再使用它了。相反,我们在DataGridTemplateColumn中使用ComboBox CellEditingTemplate,在TextBlock 中使用CellTemplate(就像您正在做的那样)

为了能够根据Id显示数据(为了在TextBlock中获得与ComboBox中相同的功能),我们使用名为CodeToDescriptionConverter的转换器。它可以像这样使用

<TextBlock>
    <TextBlock.Text>
        <MultiBinding>
            <MultiBinding.Converter>
                <con:CodeToDescriptionConverter CodeAttribute="Id"
                                                StringFormat="{}{0} - {1}">
                    <con:CodeToDescriptionConverter.DescriptionAttributes>
                        <sys:String>Id</sys:String>
                        <sys:String>Name</sys:String>
                    </con:CodeToDescriptionConverter.DescriptionAttributes>
                </con:CodeToDescriptionConverter>
            </MultiBinding.Converter>
            <Binding Path="UnitId"/>
            <Binding Path="Units"/>
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>
  • 第一个Binding是我们查找的值(Id)
  • 第二个Binding是我们查看的IList
  • CodeAttribute是我们要与ID进行比较的属性的名称(第一个Binding
  • DescriptionAttributes是我们要返回的格式为StringFormat
  • 的属性

在您的情况下:在Units中查找属性IdUnitId具有相同值的实例,并为此实例返回Id和{的值{1}}格式为Name

{0} - {1}使用反射来实现此目标

CodeToDescriptionConverter

我在这里上传了一个示例应用程序:CodeToDescriptionSample.zip 它包含public class CodeToDescriptionConverter : IMultiValueConverter { public string CodeAttribute { get; set; } public string StringFormat { get; set; } public List<string> DescriptionAttributes { get; set; } public CodeToDescriptionConverter() { StringFormat = "{0}"; DescriptionAttributes = new List<string>(); } public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { if (values.Length != 2 || values[0] == DependencyProperty.UnsetValue || values[1] == DependencyProperty.UnsetValue || values[0] == null || values[1] == null) { return null; } string code = values[0].ToString(); IList sourceCollection = values[values.Length - 1] as IList; object[] returnDescriptions = new object[DescriptionAttributes.Count]; foreach (object obj in sourceCollection) { PropertyInfo codePropertyInfo = obj.GetType().GetProperty(CodeAttribute); if (codePropertyInfo == null) { throw new ArgumentException("Code Property " + CodeAttribute + " not found"); } string codeValue = codePropertyInfo.GetValue(obj, null).ToString(); if (code == codeValue) { for (int i = 0; i < DescriptionAttributes.Count; i++) { string descriptionAttribute = DescriptionAttributes[i]; PropertyInfo descriptionPropertyInfo = obj.GetType().GetProperty(descriptionAttribute); if (descriptionPropertyInfo == null) { throw new ArgumentException("Description Property " + descriptionAttribute + " not found"); } object descriptionObject = descriptionPropertyInfo.GetValue(obj, null); string description = ""; if (descriptionObject != null) { description = descriptionPropertyInfo.GetValue(obj, null).ToString(); } returnDescriptions[i] = description; } break; } } // Ex. string.Format("{0} - {1} - {2}", arg1, arg2, arg3); return string.Format(StringFormat, returnDescriptions); } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotSupportedException(); } } DataGridTemplateColumnCodeToDescriptionConverter,它们执行相同的操作。希望这有帮助