Формат строки ячейки WPF DataGrid как стиль или шаблон - PullRequest
8 голосов
/ 07 июня 2011

Я пробовал несколько способов выделить формат ячейки в WPF DataGrid (тот, который поставляется с .NET 4):

  • преобразователь данных,
  • the "Свойство привязки 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?

1 Ответ

3 голосов
/ 16 марта 2012

Создайте свой собственный DataGridTextColumn и создайте привязки, чтобы назначить их элементу и элементу 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, а затем создать столбец в таблице данных.

Тогда все должно быть хорошо

u_u

...