使用行为为 AutoGenerated DataGrid 文本框设置文本换行

Set Text Wrapping for an AutoGenerated DataGrid TextBox using a behavior

我正在尝试将自动生成的 DataGrid 列的 TextBox 设置为使用行为换行文本。但是,在 AutoGeneratingColumn 事件期间设置 属性 不起作用。我设置正确 属性 还是有什么问题?

这是 DataGrid 的 XAML:

<DataGrid x:Name="TableGrid" ItemsSource="{Binding GridData}" AutoGenerateColumns="True">
   <i:Interaction.Behaviors>
      <b:AutoHeaderBehavior/>
   </i:Interaction.Behaviors>
</DataGrid>

下面是行为代码:

public class AutoHeaderBehavior : Behavior<DataGrid>
{
   protected override void OnAttached()
   {
      base.OnAttached();
      this.AssociatedObject.AutoGeneratingColumn += OnGeneratingColumn;
   }

   protected override void OnDetaching()
   {
      this.AssociatedObject.AutoGeneratingColumn -= OnGeneratingColumn;
      base.OnDetaching();
   }

   private void OnGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
   {
      if (e.PropertyDescriptor is PropertyDescriptor descriptor)
      {
         e.Column.Header = descriptor.DisplayName ?? descriptor.Name;
         if (descriptor.DisplayName == "Description")
         {
            var wrapping = new Setter() { Property = TextBox.TextWrappingProperty, Value = TextWrapping.Wrap };
            var style = new Style(typeof(TextBox));
            style.Setters.Add(wrapping);
            (e.Column as DataGridTextColumn).ElementStyle = style;
            e.Column.Width = 300;
         }
      }
      else
         e.Cancel = true;
   }
}

数据网格列有两种不同的模式,Non-Edit编辑,对于 DataGridTextColumn:

  • 在non-edit模式下,它显示TextBlock使用ElementStyle属性中的样式。
  • 在编辑模式下,它使用 EditingElementStyle 属性 中的样式显示 TextBox

您的代码中的问题是您将编辑样式应用于 non-edit 样式 属性。我已经调整了您的行为代码以在编辑和 non-edit 模式下包装文本。如果您只想在编辑模式下换行,只需删除 ElementStyle 属性 和相应样式的分配即可。

public class AutoHeaderBehavior : Behavior<DataGrid>
{
   protected override void OnAttached()
   {
      base.OnAttached();
      AssociatedObject.AutoGeneratingColumn += OnGeneratingColumn;
   }

   protected override void OnDetaching()
   {
      AssociatedObject.AutoGeneratingColumn -= OnGeneratingColumn;
      base.OnDetaching();
   }

   private void OnGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
   {
      if (e.PropertyDescriptor is PropertyDescriptor descriptor)
      {
         e.Column.Header = descriptor.DisplayName ?? descriptor.Name;
         if (descriptor.DisplayName == "Description")
         {
            var textWrappingSetter = new Setter
            {
               Property = TextBox.TextWrappingProperty,
               Value = TextWrapping.Wrap
            };

            // Style for non-edit mode (TextBlock)
            var elementStyle = new Style(typeof(TextBlock));
            elementStyle.Setters.Add(textWrappingSetter);

            // Style for edit mode (TextBox)
            var editingElementStyle = new Style(typeof(TextBox));
            editingElementStyle.Setters.Add(textWrappingSetter);

            var dataGridTextColumn = (DataGridTextColumn)e.Column;
            dataGridTextColumn.ElementStyle = elementStyle;
            dataGridTextColumn.EditingElementStyle = editingElementStyle;

            e.Column.Width = 300;
         }
      }
      else
      {
         e.Cancel = true;
      }
   }
}

好吧,在摆弄这个问题几个小时后,我决定通过完全更换色谱柱来解决这个问题。

private void OnGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    if (e.PropertyDescriptor is PropertyDescriptor descriptor)
    {
        e.Column.Header = descriptor.DisplayName ?? descriptor.Name;
        if (descriptor.DisplayName == "Description")
        {
            var column = new DataGridTemplateColumn();
            var element = new FrameworkElementFactory(typeof(TextBlock));
            var binding = new Binding("Description");
            var template = new DataTemplate();

            element.SetBinding(TextBlock.TextProperty, binding);
            element.SetValue(TextBox.TextWrappingProperty, TextWrapping.Wrap);
            template.VisualTree = element;
            template.Seal();
            column.CellTemplate = template;
            column.Header = e.Column.Header;
            column.Width = 300;
                
            e.Column = column;
        }
    }
    else
        e.Cancel = true;
}