8

he intentado varias formas de factorizar el formato de una celda en una cuadrícula de datos WPF (el proporcionado con .NET 4):WPF DataGrid formato de cadena de células como un estilo o una plantilla

  • un convertidor de datos,
  • la propiedad de enlace "StringFormat" dentro de un estilo,
  • la propiedad de enlace "StringFormat" dentro de una plantilla de datos.

Describiré mis intentos, ya que podría ayudar a alguien más, y espero que alguien me puede aconsejar para mejorar estas soluciones. Tenga en cuenta que soy bastante nuevo en WPF ...

El comportamiento esperado es que la cadena de la celda está formateada en algo específico como "1,234,567" para su visualización, pero debe formatearse como "1234567" (su formateo predeterminado) cuando editando la celda Cuando traté de usar un convertidor de datos, no encontré la manera de usar el formato predeterminado al editar, así que concentré mi energía en los estilos y las plantillas.

Con un estilo, la definición de la DataGridTextColumn dice así:

<DataGridTextColumn Header="Price (Style)" SortMemberPath="BILL_PRICE"> 
    <DataGridTextColumn.ElementStyle> 
     <Style TargetType="{x:Type TextBlock}"> 
      <Setter Property="Text" Value="{Binding Path=BILL_PRICE, StringFormat={}{0:N0}}"/> 
     </Style> 
    </DataGridTextColumn.ElementStyle> 
    <DataGridTextColumn.EditingElementStyle> 
     <Style TargetType="{x:Type TextBox}"> 
      <Setter Property="Text" Value="{Binding Path=BILL_PRICE}"/> 
      <Setter Property="Padding" Value="0"/> 
      <Setter Property="BorderThickness" Value="0"/> 
     </Style> 
    </DataGridTextColumn.EditingElementStyle> 
</DataGridTextColumn> 

El comportamiento es exactamente lo que se espera. Sin embargo, no puedo restar importancia a este estilo y usarlo varias veces, debido a la unión. Para resolver el problema del factoring, utilicé DataGridTemplateColumn y plantillas de datos. Aquí está mi definición DataGridTemplateColumn:

<DataGridTemplateColumn Header="Price (Template)" SortMemberPath="BILL_PRICE"> 
    <DataGridTemplateColumn.CellTemplate> 
     <DataTemplate> 
      <ContentControl Content="{Binding BILL_PRICE}" Template="{StaticResource CurrencyCellControlTemplate}"/> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellTemplate> 
    <DataGridTemplateColumn.CellEditingTemplate> 
     <DataTemplate> 
      <ContentControl Content="{Binding BILL_PRICE, Mode=TwoWay}" Template="{StaticResource CurrencyCellEditingControlTemplate}"/> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellEditingTemplate> 
</DataGridTemplateColumn> 

Y la definición ControlTemplate:

<ControlTemplate x:Key="CurrencyCellControlTemplate" TargetType="ContentControl"> 
    <TextBlock Margin="2,0,2,0" Padding="0" TextAlignment="Right"> 
     <TextBlock.Text> 
      <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Content" StringFormat="{}{0:N0}"/> 
     </TextBlock.Text> 
    </TextBlock> 
</ControlTemplate> 

<ControlTemplate x:Key="CurrencyCellEditingControlTemplate" TargetType="ContentControl"> 
    <TextBox Padding="0" BorderThickness="0" TextAlignment="Right"> 
     <TextBox.Text> 
      <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Content"/> 
     </TextBox.Text> 
    </TextBox> 
</ControlTemplate> 

El uso de plantillas de datos resuelve el problema inicial de factorización de formato de celda DataGrid, pero utilizando una plantilla de control hace aparecer ergonómico y problemas visuales . Por ejemplo, la navegación de doble pestaña causada por la plantilla de control (comentada en muchos otros lugares) y el aspecto del cuadro de texto de edición (que intento corregir con el grosor del borde, el relleno y otras configuraciones de propiedades).

preguntas específicas relacionadas con este tema son:

  • puede un convertidor de datos pueden utilizar para dar formato a la cadena para la pantalla y utilizar el formato por defecto de edición?
  • ¿Es posible factorizar el estilo DataGridTextColumn al tiempo que se puede especificar el origen de enlace?
  • ¿Hay una manera de utilizar un DataGridTemplateColumn sino simplemente hacer que se vea y se sienta como una DataGridTextColumn?
+0

Ha intentado obtener y utilizar la plantilla "por defecto" de DataGridTextColumn y sólo cambiar los bits que necesita? Probablemente necesites todos los disparadores integrados en la plantilla predeterminada. –

+0

No estoy seguro de cómo abordar esto. ¿La plantilla predeterminada está materializada como algo de XAML? Probé herramientas que muestran convenientemente las plantillas predeterminadas (se muestran como XAML cuando se selecciona un tema y un control específico) pero no había ninguna para DataGridTextColumn. ¿O quiere decir que debería obtener la plantilla predeterminada en el código y aplicarla dinámicamente a las columnas? – Thibault

Respuesta

3

Crea tu propio DataGridTextColumn personalizado y crea enlaces para asignar al Element y al EditingElement (uno de ellos con un convertidor sin uno de ellos).

El convertidor formatea la cadena para parecerse a un número decimal con las comas.

public class MyDataGridTextColumn : DataGridTextColumn 
{ 
    Binding formattedBinding; 
    Binding unformattedBinding; 
    FormatConverter formatConverter = new FormatConverter(); 

    protected override FrameworkElement 
    GenerateElement(DataGridCell cell, object dataItem) 
    { 
     var element = base.GenerateElement(cell, dataItem) as TextBlock; 
     element.SetBinding(TextBlock.TextProperty, GetFormattedTextBinding()); 
     return element; 
    } 

    protected override FrameworkElement 
    GenerateEditingElement (DataGridCell cell, object dataItem) 
    { 
     var element = base.GenerateEditingElement(cell, dataItem) as TextBox; 
     element.SetBinding(TextBox.TextProperty, GetTextBinding()); 
     return element; 
    } 

    Binding 
    GetTextBinding() 
    { 

      var binding = (Binding)Binding; 
      if (binding == null) return new Binding(); 
      unformattedBinding = new Binding 
      { 
       Path = binding.Path, 
       Mode=BindingMode.TwoWay 
      }; 

     return unformattedBinding; 
    } 

    Binding 
    GetFormattedTextBinding() 
    { 
     var binding = (Binding)Binding; 
      if (binding == null) return new Binding(); 
      formattedBinding = new Binding 
      { 
       Path = binding.Path, 
       Converter = Formatter, 
      }; 

     return formattedBinding; 
    } 

    public FormatConverter 
    Formatter 
    { 
     get { return formatConverter; } 
     set { formatConverter = value; } 
    } 
} 
public class FormatConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     string textvalue = value as string; 
     if (!string.IsNullOrEmpty(textvalue)) 
     { 
      decimal decimalvalue = decimal.Parse(textvalue); 
      var test = String.Format("{0:0,0.00}", decimalvalue); 
      return test; 
     } 
     else 
      return ""; 

    } 
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new InvalidOperationException("FormatConverter can only be used OneWay."); 
    } 
} 

Yo no entiendo cómo la cadena de formato informados obras así que hice una simple, si quieres más lugares decimales simplemente a solucionar el problema en el convertidor.

Todo lo que necesita hacer ahora es hacer una referencia al espacio de nombre en su xaml y luego crear una columna en la cuadrícula de datos.

Entonces todos deben estar bien

u_u

+0

De hecho, la subclasificación es el camino a seguir. Al principio estaba buscando una forma puramente en XAML, pero parece imposible sin una DataGridColumn personalizada. – Thibault

+0

@Jason Ridge en serio? Para formatear el contenido en celdas de una columna, esta solución es increíblemente intrincada. –

Cuestiones relacionadas