我想用multilevel(2 level)列标题模仿Datagrid。我将使用DataGrid顶部的Grid定义第一级,第二级将是datagrid标头本身,如下所示:
我现在遇到的问题(可能是在值守会议上)是我希望GridColumn1
的宽度始终是DataGridColumn1
和DataGridColumn2
列的宽度之和。为此,我创建了值转换器:
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}">
答案 0 :(得分:1)
问题中的转换器有两个问题:
从ActualWidth
属性馈送到转换器的值是double
类型,但是转换器将它们转换为整数值。这将导致舍入错误,导致转换器结果有些不准确。
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;
}
}