如何在datagrid列中多重绑定数据和StringFormat?

时间:2013-10-01 16:12:34

标签: wpf datagrid string-formatting

我有一个WPF DataGrid,其数字列最初的格式没有小数。

用户有一个复选框,可以选择数字格式显示0或2个小数位。下面显示了列的xaml。

<DataGridTemplateColumn Header="Qty" Width="40" IsReadOnly="False" CellStyle="{StaticResource EditCell}">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ItemQuantity, StringFormat={}{0:#}}" TextAlignment="Right" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <TextBox x:Name="textbox"  BorderThickness="0" HorizontalContentAlignment="Right" Background="LightYellow">
                <Binding Path="ItemQuantity" StringFormat="N0" UpdateSourceTrigger="LostFocus" >
                    <Binding.ValidationRules>
                        <c:DecimalRangeRule Min="0" Max="999999.99"/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

如果更改复选框,如何更改列StringFormat设置?

编辑:解决方案

我使用MultiConverter(根据nit建议)根据是否选中复选框选择格式:

//==========================================================================
public class NumericFormatConverter : IMultiValueConverter
{
    private const string FormatN0 = "{0:#,##0;-#,##0; }";
    private const string FormatN2 = "{0:#,##0.00;-#,##0.00; }";

    public object Convert( object[] values, Type targetType, object parameter, CultureInfo culture )
    {
        if ( values[0] == null ) return string.Empty;

        decimal num = 0;
        Decimal.TryParse( values[0].ToString(), out num );

        string format = FormatN0;
        bool isSmallValue = (values[1] == null ? false : (bool)values[1]);
        if ( isSmallValue ) format = FormatN2;

        return String.Format( format, num );
    }

    public object[] ConvertBack( object value, Type[] targetTypes, object parameter, CultureInfo culture )
    {
        decimal num = 0;
        Decimal.TryParse( value.ToString(), out num );

        object[] objects = new object[1] {num};
        return objects;
    }
}

DataGridTemplateColumn已更改为使用MultiBinding:

<DataGridTemplateColumn Header="Qty" Width="40" IsReadOnly="False"  CellStyle="{StaticResource EditCell}">
    <DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <TextBlock HorizontalAlignment="Right" >
                <TextBlock.Text>
                <MultiBinding Converter="{StaticResource NumericFormat}">
                <Binding Path="GroupQuantity" />
                <Binding ElementName="chkSmallValue" Path="IsChecked"/>
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
    </DataTemplate>

    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
        <TextBox x:Name="textbox" BorderThickness="0" HorizontalContentAlignment="Right" Background="LemonChiffon" PreviewTextInput="TextBox_PreviewTextInput" >
            <MultiBinding Converter="{StaticResource NumericFormat}"  UpdateSourceTrigger="LostFocus">
            <Binding Path="GroupQuantity" />
            <Binding ElementName="chkSmallValue" Path="IsChecked" Mode="OneWay"/>
            </MultiBinding>
        </TextBox>
    </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

3 个答案:

答案 0 :(得分:3)

由于StringFormat不是依赖属性,因此无法将其绑定到任何值以进行更改。 要更改它,您必须在单元格的visualtree中找到TextBlock,然后在后面的代码中更改BindingExpression的StringFormat。但这种方法很糟糕。

您可以做的是不使用StringFormat而是使用MultiValueConverter将TextBlock.Text多重绑定到Checkbox IsChecked属性和ItemQuantity。在转换器中,您可以根据复选框的IsChecked

返回格式化的字符串

答案 1 :(得分:1)

您可以使用Checkbox的“Checked”和“Unchecked”事件在代码中设置绑定。

private void HandleCheck(object sender, RoutedEventArgs e)
{
    var binding = new Binding
    {
        Path = new PropertyPath("ItemQuantity"),
        StringFormat = "{0:0.00}"
    };
    textBoxName.SetBinding(TextBox.TextProperty, binding);
}

private void HandleUnchecked(object sender, RoutedEventArgs e)
{
    var binding = new Binding
    {
        Path = new PropertyPath("ItemQuantity"),
        StringFormat = "{0:0}"
    };
    textBoxName.SetBinding(TextBox.TextProperty, binding);

}

private void HandleCheck(object sender, RoutedEventArgs e) { var binding = new Binding { Path = new PropertyPath("ItemQuantity"), StringFormat = "{0:0.00}" }; textBoxName.SetBinding(TextBox.TextProperty, binding); } private void HandleUnchecked(object sender, RoutedEventArgs e) { var binding = new Binding { Path = new PropertyPath("ItemQuantity"), StringFormat = "{0:0}" }; textBoxName.SetBinding(TextBox.TextProperty, binding); }

答案 2 :(得分:0)

您可以使用EventToCommandTrigger将您带到ViewModel,您可以在那里更改ItemQuantity中的小数位数。

在ViewModel中执行此操作将允许您围绕功能编写单元测试以进行测试。