假设我有一个像这样定义的DataGrid
<DataGrid AreRowDetailsFrozen="True"
ItemsSource="{Binding MyCollection}"
AutoGenerateColumns="False">
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Border CornerRadius="5" BorderBrush="Red"
BorderThickness="2" Background="Black">
<TextBlock Foreground="White" Text="{Binding RowDetails}"
TextWrapping="Wrap"/>
</Border>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
<DataGrid.Columns>
<DataGridTextColumn Header="0" Binding="{Binding Value1}"/>
<DataGridTextColumn Header="1" Binding="{Binding Value2}"/>
<DataGridTextColumn Header="2" Binding="{Binding Value3}"/>
<DataGridTextColumn Header="3" Binding="{Binding Value4}"/>
</DataGrid.Columns>
</DataGrid>
使用和不使用RowDetails
时看起来像这样
在右边的图片中,我得到了一个永不包裹的非常长的DataGridRow 是否可以让RowDetails使用与DataGrid相同的宽度而不影响Width本身?
我尝试过的东西实现了包装但不是令人满意的方式
答案 0 :(得分:13)
这就是我最终要做的事情。我宁愿在DataGrid上使用一个属性,但由于没有这样的属性,我需要一个解决方法。
首先,我只使用了父DataGrid中的ActualWidth,并删除了一个常数9.这首先工作但是当垂直滚动条变得可见时失败,所以我不得不使用MultiBinding。
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Border HorizontalAlignment="Left" CornerRadius="5"
BorderBrush="Red" BorderThickness="2" Background="Black">
<Border.Width>
<MultiBinding Converter="{StaticResource RowDetailsWidthMultiConverter}"
ConverterParameter="9">
<Binding RelativeSource="{RelativeSource AncestorType={x:Type DataGrid}}"
Path="ActualWidth"/>
<Binding RelativeSource="{RelativeSource AncestorType={x:Type ScrollViewer}}"
Path="ComputedVerticalScrollBarVisibility"/>
</MultiBinding>
</Border.Width>
<TextBlock Foreground="White" Text="{Binding RowDetails}" TextWrapping="Wrap"/>
</Border>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
在转换器中,我使用另一个常量(16)来补偿可见的垂直滚动条(如果它可见)。
public class RowDetailsWidthMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double originalWidth = (double)values[0];
Visibility verticalScrollbarVisibility = (Visibility)values[1];
double subtractWidth = System.Convert.ToDouble(parameter);
double returnWidth = originalWidth - subtractWidth;
if (verticalScrollbarVisibility == Visibility.Visible)
{
return returnWidth - 16;
}
return returnWidth;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
更新
我对解决方案进行了一些改进,使用ActualWidth为ItemsPresenter而不是DataGrid(其中ActualWidth没有根据可见的ScrollBar而改变),因此不再需要MultiConverter和两个常量。
<DataGrid.Resources>
<local:SubtractConstantConverter x:Key="SubtractConstantConverter"/>
</DataGrid.Resources>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Border HorizontalAlignment="Left" CornerRadius="5"
BorderBrush="Red" BorderThickness="2" Background="Black"
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsPresenter}},
Path=ActualWidth,
Converter={StaticResource SubtractConstantConverter},
ConverterParameter=6}">
<TextBlock Foreground="White" Text="{Binding RowDetails}" TextWrapping="Wrap"/>
</Border>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
<强> SubtractConstantConverter 强>
public class SubtractConstantConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double originalValue = (double)value;
double subtractValue = System.Convert.ToDouble(parameter);
return originalValue - subtractValue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
答案 1 :(得分:13)
这里的答案感觉就像一个解决方法所以我做了一些研究,并确实在Telerik论坛上找到了解决方案,因为我们使用他们的RadGridView。结果证明该解决方案也适用于DataGrid。
关键是将ScrollViewer.HorizontalScrollBarVisibility属性设置为Disabled,请参阅下面的示例。
<DataGrid ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Border>
<TextBlock Foreground="White" Text="{Binding RowDetails}"
TextWrapping="Wrap"/>
</Border>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
编辑: 副作用是,如果列需要更多的水平空间,那么它们将被剪裁。因此,如果这是一个问题,那么这个解决方案不是最佳的。
答案 2 :(得分:4)
这就是我最终要做的事情:将行细节宽度绑定到其演示者的实际宽度,然后添加一个不同厚度的边框,以补偿演示者中是否存在垂直滚动条。这种方法对我来说非常合适。示例xaml:
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Border BorderThickness="2,2,8,2"
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsPresenter}}, Path=ActualWidth}"
HorizontalAlignment="Left" >
<!-- add the row details view contents here -->
</Border>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
答案 3 :(得分:2)
您可以将MaxWidth绑定到ElementName=PART_ColumnHeadersPresenter, Path=ActualWidth
或RenderSize.Width。我相信这是显示列的DataGrid模板的一部分,所以理论上它应该可以工作
答案 4 :(得分:2)
谢谢Meleak,您的解决方案对我有用。 WPF新手的一个小小的补充。请务必将Converter类声明为资源,以便可以在Binding表达式中引用它。
我把它放在App.Xaml中,就像这样:
<Application x:Class="ISCBilling.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:my.application.namespace"
StartupUri="IscBillingWindow.xaml">
<Application.Resources>
<conv:RowDetailsWidthMultiConverter x:Key="RowDetailsWidthMultiConverter" />
</Application.Resources>
</Application>
答案 5 :(得分:1)
为了节省其他人一些头痛和试错时间:
经过与Fredrik Hedblad最近(1/1/11)solution的争吵一段时间后,我发现 ConverterParameter 值应 6 + [left margin} + [右边距] (即模板中最外层容器的边距。)在检查了屏幕截图的爆破后,我希望 6 是垂直条的宽度。每行左边。