我有TreeViewItem
s HierarchicalDataTemplate
由一个包含3列的网格组成,其中包含以下定义:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="Auto" />
...
我想设置网格的宽度,以便它会占用TreeViewItem
内TreeView
的所有可用空间。因此,网格的第三列应在TreeView
内右对齐。
如何获得网格宽度的正确值?
我知道对于ListBox
ItemTemplate
,我可以通过将宽度绑定到ScrollContentPresenter
来设置宽度:
Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ScrollContentPresenter, AncestorLevel=1}, Path=ActualWidth}"
这个技巧在TreeView
中不起作用,因为子项的可用空间比根树视图项少。
有什么想法吗?
答案 0 :(得分:6)
在使用它几个小时后,我找到了一个使用多重绑定和两个转换器的工作解决方案。
首先,XAML中HierarchicalDataTemplate
的定义:
<HierarchicalDataTemplate>
<Grid>
<Grid.Width>
<MultiBinding Converter="{StaticResource SumConverterInstance}">
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=ScrollContentPresenter, AncestorLevel=1}" Path="ActualWidth" />
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=TreeViewItem, AncestorLevel=1}" Converter="{StaticResource ParentCountConverterInstance}" />
</MultiBinding>
</Grid.Width>
.... (content of the template) ....
</Grid>
</HierarchicalDataTemplate>
multibinding中的第一个绑定获得ScrollContentPresenter
中TreeView
的宽度,这是TreeView
的总可见宽度。第二个绑定调用带有TreeViewItem
作为参数的转换器,并计算TreeViewItem
在到达根项之前有多少父项。使用这两个输入,我们使用Multibinding
中的SumConverterInstance来计算给定TreeViewItem
的可用宽度。
以下是XAML中定义的转换器实例:
<my:SumConverter x:Key="SumConverterInstance" />
<my:ParentCountConverter x:Key="ParentCountConverterInstance" />
和两个转换器的代码:
// combine the width of the TreeView control and the number of parent items to compute available width
public class SumConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double totalWidth = (double)values[0];
double parentCount = (double)values[1];
return totalWidth - parentCount * 20.0;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
// count the number of TreeViewItems before reaching ScrollContentPresenter
public class ParentCountConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int parentCount = 1;
DependencyObject o = VisualTreeHelper.GetParent(value as DependencyObject);
while (o != null && o.GetType().FullName != "System.Windows.Controls.ScrollContentPresenter")
{
if (o.GetType().FullName == "System.Windows.Controls.TreeViewItem")
parentCount += 1;
o = VisualTreeHelper.GetParent(o);
}
return parentCount;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
现在看起来是正确的:
答案 1 :(得分:1)
您应该让布局系统为您处理此问题,而不是强制ItemTemplate
中的固定宽度。对于ListBox
,您只需设置HorizontalContentAlignment="Stretch"
即可。这也是TreeView
的第一步,但不幸的是,默认模板中还有一些需要进行额外更改的其他布局。它使用3列Grid,将内容放入第二列,只有子项扩展到第三列(*)。通过在包含Grid.ColumnSpan="2"
的{{1}}上添加ContentPresenter
,内容将覆盖整个项目的区域。
Border
答案 2 :(得分:0)
您所描述的是TreeView
的{{1}},我上面描述的网格是ItemContainerStyle
。
在我的HierarchicalDataTemplate
我正在显示电子邮件附件。 TreeView
包含一个图标(网格的第一列),文件名和大小(第二列)和时间(第三列)。我希望根据TreeViewItem
的宽度看到拉伸或挤压的项目(通过包裹网格的中间列)。
以下是一个非工作示例。正如您所看到的,文件名未被包装,因此您无法看到某些项目的日期。