3

我用谷歌搜索,但运气非常有限。我有一个关于可编辑 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

4

1 回答 1

3

实现相同目的的最简单方法是使用DataGridComboBoxColumn.

然而,在我目前的项目中,我们遇到了很多问题,DataGridComboBoxColumn以至于我们不再使用它。相反,我们使用DataGridTemplateColumna ComboBoxin theCellEditingTemplate和 a TextBlockin the 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)
  • 第二个BindingIList我们看的
  • CodeAttribute是我们要与 id 比较的属性的名称(第一个Binding
  • DescriptionAttributes是我们想要返回的属性,格式为StringFormat

在您的情况下:找到Units属性Id具有相同值的UnitId实例,对于该实例,返回值IdName格式化为{0} - {1}

CodeToDescriptionConverter使用反射来实现这一点

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

我在这里上传了一个示例应用程序:CodeToDescriptionSample.zip
它包括 a DataGridTemplateColumnwithCodeToDescriptionConverter和 a DataGridComboBoxColumnthat 做同样的事情。希望这可以帮助

于 2012-06-06T10:22:06.077 回答