9

WPF DataGrid(.NET 4で提供されているもの)のセルの形式を除外するいくつかの方法を試しました。

  • データコンバーター、
  • スタイル内の「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の定義:

<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のように見えるようにする方法はありますか?
4

1 に答える 1

4

独自のカスタムDataGridTextColumnを作成し、要素とEditingElementに割り当てるバインディングを作成します(そのうちの1つにはコンバーターがあり、もう1つにはコンバーターがありません)。

コンバーターは、文字列をコンマ付きの小数のようにフォーマットします。

 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に名前空間への参照を配置してから、データグリッドに列を作成することです。

その後、すべてがうまくいくはずです

u_u

于 2012-03-16T14:16:57.907 に答える