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