8

我尝试了几种方法来分析出在WPF数据网格中的单元格(提供.NET 4中的一个)的格式:WPF DataGrid单元格字符串格式的样式或模板

  • 数据转换器,
  • 样式中的“StringFormat”绑定属性,数据模板中的“StringFormat”绑定属性。

我将描述我的尝试,因为它可能会帮助别人,我希望有人可以给我建议,以改善这些解决方案。请注意,我是相当新的WPF ...

预期的行为是单元格字符串被格式化为某些特定的“1,234,567”显示,但它应格式化为“1234567”(其默认格式)时编辑单元格。当我尝试使用数据转换器时,编辑时没有找到使用默认格式的方法,所以我将精力集中在样式和模板上。

有了风格,DataGridTextColumn的定义是这样的:

<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> 

行为正是预期。但是,由于绑定的原因,我不能将这种风格分解并多次使用。为了解决保理问题,我使用了DataGridTemplateColumn和数据模板。这里是我的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> 

而且控件模板定义:

<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> 

使用数据模板解决分解出的DataGrid单元格的格式,但使用控制模板的初始问题带来了符合人体工程学,视觉问题。例如,由控制模板引起的双标签导航(在许多其他地方讨论过)以及编辑文本框的外观(我尝试使用边框厚度,填充和其他属性设置来修复)。

与此问题有关的具体问题是:

  • 可以使用数据转换器来格式化显示的字符串并使用默认格式进行编辑?
  • 是否有可能将DataGridTextColumn样式分解,同时仍然能够指定绑定源?
  • 有没有办法使用DataGridTemplateColumn,但只是使它看起来和感觉像一个DataGridTextColumn?
+0

您是否尝试过获取和使用DataGridTextColumn的“默认”模板,只改变了你所需要的位?您可能需要将所有触发器内置到默认模板中。 – 2011-06-07 09:33:01

+0

我不确定如何解决这个问题。是否将默认模板物化为一些XAML?我尝试了方便地显示默认模板的工具(在选择主题和特定控件时显示为XAML),但DataGridTextColumn没有。或者你的意思是我应该在代码后面获取默认模板并将其动态应用到列中? – Thibault 2011-06-09 06:33:53

回答

3

制作您自己的自定义DataGridTextColumn并创建绑定以分配给Element和EditingElement(其中一个没有使用其中一个转换器)。

转换器将字符串格式化为与逗号相似的小数。

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."); 
    } 
} 

我不明白你怎么贴作品格式化字符串所以我做了一个简单的,如果你想要更多的小数位只是排序它在该转换器。

您现在需要做的就是在xaml中放置对命名空间的引用,然后在datagrid中创建一列。

然后,所有应该很好

u_u

+0

事实上,子类化是要走的路。我首先在纯粹的XAML中寻找一种方式,但没有自定义的DataGridColumn似乎是不可能的。 – Thibault 2012-03-19 05:12:57

+0

@Jason Ridge认真吗?要格式化列的单元格中的内容,此解决方案令人难以置信地令人费解。 – 2015-04-17 05:23:19