Reputation: 365
I want to make imitation of Datagrid with multilevel(2 level) column header. I am going to define first level with Grid on top of datagrid and the second level will be datagrid header itself as shown below:
The problem I have now (Which is probably in valueconventer) is that I want the width of GridColumn1
always to be sum of widths' of DataGridColumn1
and DataGridColumn2
columns. For this, I have created value converter:
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 };
}
}
And Defined the GridColumn1
as shown below:
<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
looks like this:
<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>
This code for some reason doesn't work. I run it successfully, buy the width of GridColumn is as it was without binding.
P.S If I want to bind DataGridColumn1
column's width to GridColumn1
, this works:
<ColumnDefinition Width="{Binding ElementName=Column1, Path=ActualWidth}">
Upvotes: 1
Views: 1473
Reputation:
The converter in the question has two problems:
The values fed from the ActualWidth
properties to the converter are of type double
, but the converter converts them into integer values. This will cause rounding errors, causing the converter result to be somewhat inaccurate.
The ColumnDefinition.Width
is of type GridLength
. The targetType argument of the converter's Convert method will also tell this. Since a integer or floating point value is not implicitely/explictely convertible to GridLength, the converter itself has to produce and return such a GridLength object. Otherwise, the binding mechanism will reject the result produced by the converter.
Addressing the two issues, a working Convert method could look for example like this:
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;
}
}
Upvotes: 1