在WPF中将Width绑定到两个元素的ActualWidths之和

时间:2018-10-27 09:16:51

标签: c# wpf

我想用multilevel(2 level)列标题模仿Datagrid。我将使用DataGrid顶部的Grid定义第一级,第二级将是datagrid标头本身,如下所示:

enter image description here

我现在遇到的问题(可能是在值守会议上)是我希望GridColumn1的宽度始终是DataGridColumn1DataGridColumn2列的宽度之和。为此,我创建了值转换器:

public class DataGridExtraHeaderConventer : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            int actualWidth = 0;

            foreach (var item in values)
            {
                actualWidth += System.Convert.ToInt32(item);
            }

            return actualWidth;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            var x = DependencyProperty.UnsetValue;
            var y = DependencyProperty.UnsetValue;
            return new object[] { x, y };
        }
    }

并按如下所示定义GridColumn1

<Grid.ColumnDefinitions>
                <ColumnDefinition>
                    <ColumnDefinition.Width>
                        <MultiBinding Converter="{StaticResource DataGridExtraHeaderConventer }">
                            <Binding ElementName="Column1" Path="ActualWidth"/>
                            <Binding ElementName="Column2" Path="ActualWidth"/>
                        </MultiBinding>
                    </ColumnDefinition.Width>
                </ColumnDefinition>
                <ColumnDefinition Width="*" />

Datagrid看起来像这样:

<DataGrid Name="datagrid1" AutoGenerateColumns="False" Grid.Row="3" RowHeaderWidth="10">
            <DataGrid.Columns>
                <DataGridTextColumn x:Name="Column1" Binding="{Binding something}" Header="column 1" Width="50*" />
                <DataGridTextColumn x:Name="Column2" Binding="{Binding something}"  Header="column 2" Width="60*" />
                <DataGridTextColumn x:Name="Column3" Binding="{Binding something}" Header="column 3" Width="80" />
                <DataGridTextColumn x:Name="Column4" Binding="{Binding something}" Header="column 4" Width="*" />
            </DataGrid.Columns>
        </DataGrid>

由于某些原因,此代码不起作用。我成功运行了它,买了GridColumn的宽度保持不变,没有绑定。

P.S如果我想将DataGridColumn1列的宽度绑定到GridColumn1,则可以这样做:

<ColumnDefinition Width="{Binding ElementName=Column1, Path=ActualWidth}">

1 个答案:

答案 0 :(得分:1)

问题中的转换器有两个问题:

  1. ActualWidth属性馈送到转换器的值是double类型,但是转换器将它们转换为整数值。这将导致舍入错误,导致转换器结果有些不准确。

  2. ColumnDefinition.Width的类型为GridLength。转换器的 Convert 方法的 targetType 参数也可以说明这一点。由于整数或浮点值不能隐式/明示地转换为 GridLength ,因此转换器本身必须产生并返回这样的 GridLength 对象。否则,绑定机制将拒绝转换器产生的结果。

为解决这两个问题,有效的 Convert 方法可能看起来像这样:

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
    try
    {
        double sumActualWidths = values.Sum(v => System.Convert.ToDouble(v));
        if (targetType == typeof(GridLength))
            return new GridLength(sumActualWidths);
        else
            return System.Convert.ChangeType(sumActualWidths, targetType);
    }
    catch (Exception ex)
    {
        Oops! Something went wrong.
        I better handle this exception in a meaningful way.

        return Binding.DoNothing;
    }
}