分层模板格式化问题/问题
Hierarchical Template Formatting Problems / Questions
我有几个关于 TreeView 的分层模板格式的问题。此图片将说明:
- 我想删除字体顶部和边框之间多余的 space。
- 我想将图标居中放置在两行文字
之间
- 我想加一个千位逗号。我已经试过了,但是添加带有绑定数据的逗号时出现问题。
这里是第三层的XAML代码:
<HierarchicalDataTemplate
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
ItemsSource="{Binding XPath=Unit}"
>
<Grid Height="42" Width="auto" >
<Grid Height="41" HorizontalAlignment="Left" Margin="0,0,0,0" Name="grid1" VerticalAlignment="Top" Width="auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Image Source= "{Binding XPath=UnitIcon}" Grid.Column="1" Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Left" Stretch="None" OpacityMask="White"></Image>
<Label Content="{Binding XPath=UnitName}" Height="54" HorizontalAlignment="Left" Name="label4" VerticalAlignment="Top" FontFamily="Smythe" FontSize="18" Margin="0,0,0,0" Grid.RowSpan="3" Grid.Column="2" Grid.ColumnSpan="3"/>
<Label Content="Strength:" FontFamily="Amaltea WF" FontSize="12" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Center" Grid.Column="2" Grid.Row="2"/>
<TextBlock Text="{Binding XPath=UnitStrength, ConverterParameter=N0}" Margin="0,0,0,0" FontFamily="BauderieScriptSSK Bold" FontSize="18" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Column="3" Grid.Row="2"/>
</Grid>
<Line X1='0'
X2='200'
Y1='0'
Y2='0'
Stroke="Gray"
StrokeThickness='1' />
</Grid>
</HierarchicalDataTemplate>
在此先感谢您的帮助!
去掉 UnitName 标签上的固定高度。你有网格单元,你不想要固定的高度。该间隙的一部分可能是您字体的行高。暂时在标签上设置Background="LightSkyBlue"
,看看标签本身实际占用了多少space。
看起来图像上的 VerticalAlignment="Center"
没有达到预期的效果,因为您在所有内容上设置了相互冲突的固定高度。您的 grid1
固定为 41 个单位高,但其中的单位名称为 54 个单位高。布局引擎正在尽最大努力遵守您给它的相互矛盾的命令。
删除 XAML 中的每个固定高度。每一个,无一例外。让事情自行调整。如果您绝对必须对控件施加固定高度,请考虑将其内容放在 ViewBox
中,这样内容可以动态调整自己的大小而不会溢出容器。或不;这看起来很奇怪。但是首先让你的相对布局工作,然后开始努力将它塞进你已经得到的任何有限的 space 中。
当您在 XAML 布局方面遇到问题时,天真的冲动是添加内容。最糟糕的是,添加 random 东西 -- "I don't know what this property means or what its value means, but maybe if I add it on this control, it'll fix what's wrong with the other one!" -- 在 best,你添加的东西将是无害的。
不要那样做。 移除 内容,然后重新构建。 一次添加一个东西,看看它的作用。并添加 nothing 而无需先阅读其文档。从 Intellisense 添加六个随机属性 似乎 比在 MSDN 上查找一个 属性 花费的时间更少,但事实并非如此,因为第一种方法是总是保证完全浪费时间。这就像闭上眼睛开车,并试图根据撞到障碍物的感觉来控制方向。
您将正确的格式字符串分配给了错误的 属性。试试这个:
<TextBlock Text="{Binding XPath=UnitStrength, StringFormat=N0}"
除了大声笑哈哈,这对 Binding.XPath
不起作用,所以我在胡说八道。这也不是:
<Label Content="{Binding XPath=UnitStrength}" ContentStringFormat="N0" />
我怀疑他们失败是因为您给了他们一个字符串而不是一个整数,但这只是一个猜测。
但这行得通。
public class IntToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int n = 0;
if (Int32.TryParse((string)value, out n))
{
value = n.ToString((String)parameter);
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML。 YOUR_NAMESPACE_HERE
是您定义 IntToStringConverter
class 的 C# 名称 space。那不一定就在那里;它可以位于此 XAML 文件中的父标签或任何包含标签上,包括根标签(Window
或 UserControl
或 ResourceDictionary
)。把它放在这里使这个例子更加独立。
<HierarchicalDataTemplate
xmlns:local="clr-namespace:YOUR_NAMESPACE_HERE"
>
<HierarchicalDataTemplate.Resources>
<local:IntToStringConverter
x:Key="IntToString"
/>
</HierarchicalDataTemplate.Resources>
<!-- blah blah -->
<TextBlock
Text="{Binding XPath=UnitStrength, Converter={StaticResource IntToString}, ConverterParameter=N0}"
/>
更新
<Window.Resources>
<!-- stuff -->
<HierarchicalDataTemplate
x:Key="UnitTemplate"
ItemsSource="{Binding XPath=Unit}"
>
<Grid Width="auto">
<!-- stuff -->
</Grid>
</HierarchicalDataTemplate>
<!-- stuff -->
</Window.Resources>
对于 TreeView:
<TreeView
...
ItemTemplate="{StaticResource UnitTemplate}"
...
/>
但是如果一个模板只在一个地方使用,这也行得通:
<TreeView
...
>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate
ItemsSource="{Binding XPath=Unit}"
>
<Grid Width="auto">
<!-- stuff -->
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
另一个更新
或者最后,如果您想将所有数据模板放在它们自己的文件中,您想要创建一个资源字典:
<Window.Resources>
<!-- If you're doing the merged thing, you have to explicitly have the
ResourceDictionary tag here.
-->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="DataTemplates.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- other resources maybe -->
</ResourceDictionary>
</Window.Resources>
DataTemplate.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ScenarioEditor"
>
<local:IntToStringConverter
x:Key="IntToString"
/>
<HierarchicalDataTemplate
x:Key="UnitTemplate"
ItemsSource="{Binding XPath=Unit}"
>
<Grid Width="auto">
<!-- stuff -->
</Grid>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
x:Key="SomeOtherTemplate"
>
<Grid Width="auto">
<!-- different stuff -->
</Grid>
</HierarchicalDataTemplate>
</ResourceDictionary>
又一个更新
所以我们正在查看的树有多个级别,每个级别都有不同的模板。至少有两种方法可以做到这一点:如果我们有一个具有不同子类型的 .NET classes 树,我们可以在资源字典中定义 "implicit templates"。他们有一个 DataType
属性而不是 x:Key
,结果是(例如)带有 DataType="{x:Type local:HQ}"
的模板将自动用于显示该属性的任何 class 实例类型。
但是你有 XML 所以这行不通。你可以做的是给每个 HierarchicalDataTemplate
一个自己的 ItemTemplate
。为清楚起见,以下示例省略了 ItemsSource
和其他许多内容——它仅说明了我们如何设置那些 parent/child 模板关系。
<HierarchicalDataTemplate
x:Key="UnitTemplate"
>
<Grid>
<!-- Unit stuff -->
</Grid>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
x:Key="CommanderTemplate"
ItemTemplate="{StaticResource UnitTemplate}"
>
<Grid>
<!-- Commander stuff -->
</Grid>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
x:Key="HQTemplate"
ItemTemplate="{StaticResource CommanderTemplate}"
>
<Grid>
<!-- HQ stuff -->
</Grid>
</HierarchicalDataTemplate>
HQTemplate
将是树视图的 ItemTemplate
<TreeView
...
ItemTemplate="{StaticResource HQTemplate}"
我有几个关于 TreeView 的分层模板格式的问题。此图片将说明:
- 我想删除字体顶部和边框之间多余的 space。
- 我想将图标居中放置在两行文字 之间
- 我想加一个千位逗号。我已经试过了,但是添加带有绑定数据的逗号时出现问题。
这里是第三层的XAML代码:
<HierarchicalDataTemplate
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
ItemsSource="{Binding XPath=Unit}"
>
<Grid Height="42" Width="auto" >
<Grid Height="41" HorizontalAlignment="Left" Margin="0,0,0,0" Name="grid1" VerticalAlignment="Top" Width="auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Image Source= "{Binding XPath=UnitIcon}" Grid.Column="1" Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Left" Stretch="None" OpacityMask="White"></Image>
<Label Content="{Binding XPath=UnitName}" Height="54" HorizontalAlignment="Left" Name="label4" VerticalAlignment="Top" FontFamily="Smythe" FontSize="18" Margin="0,0,0,0" Grid.RowSpan="3" Grid.Column="2" Grid.ColumnSpan="3"/>
<Label Content="Strength:" FontFamily="Amaltea WF" FontSize="12" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Center" Grid.Column="2" Grid.Row="2"/>
<TextBlock Text="{Binding XPath=UnitStrength, ConverterParameter=N0}" Margin="0,0,0,0" FontFamily="BauderieScriptSSK Bold" FontSize="18" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Column="3" Grid.Row="2"/>
</Grid>
<Line X1='0'
X2='200'
Y1='0'
Y2='0'
Stroke="Gray"
StrokeThickness='1' />
</Grid>
</HierarchicalDataTemplate>
在此先感谢您的帮助!
去掉 UnitName 标签上的固定高度。你有网格单元,你不想要固定的高度。该间隙的一部分可能是您字体的行高。暂时在标签上设置
Background="LightSkyBlue"
,看看标签本身实际占用了多少space。看起来图像上的
VerticalAlignment="Center"
没有达到预期的效果,因为您在所有内容上设置了相互冲突的固定高度。您的grid1
固定为 41 个单位高,但其中的单位名称为 54 个单位高。布局引擎正在尽最大努力遵守您给它的相互矛盾的命令。删除 XAML 中的每个固定高度。每一个,无一例外。让事情自行调整。如果您绝对必须对控件施加固定高度,请考虑将其内容放在
ViewBox
中,这样内容可以动态调整自己的大小而不会溢出容器。或不;这看起来很奇怪。但是首先让你的相对布局工作,然后开始努力将它塞进你已经得到的任何有限的 space 中。当您在 XAML 布局方面遇到问题时,天真的冲动是添加内容。最糟糕的是,添加 random 东西 -- "I don't know what this property means or what its value means, but maybe if I add it on this control, it'll fix what's wrong with the other one!" -- 在 best,你添加的东西将是无害的。
不要那样做。 移除 内容,然后重新构建。 一次添加一个东西,看看它的作用。并添加 nothing 而无需先阅读其文档。从 Intellisense 添加六个随机属性 似乎 比在 MSDN 上查找一个 属性 花费的时间更少,但事实并非如此,因为第一种方法是总是保证完全浪费时间。这就像闭上眼睛开车,并试图根据撞到障碍物的感觉来控制方向。
您将正确的格式字符串分配给了错误的 属性。试试这个:
<TextBlock Text="{Binding XPath=UnitStrength, StringFormat=N0}"
除了大声笑哈哈,这对
Binding.XPath
不起作用,所以我在胡说八道。这也不是:<Label Content="{Binding XPath=UnitStrength}" ContentStringFormat="N0" />
我怀疑他们失败是因为您给了他们一个字符串而不是一个整数,但这只是一个猜测。
但这行得通。
public class IntToStringConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { int n = 0; if (Int32.TryParse((string)value, out n)) { value = n.ToString((String)parameter); } return value; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
XAML。
YOUR_NAMESPACE_HERE
是您定义IntToStringConverter
class 的 C# 名称 space。那不一定就在那里;它可以位于此 XAML 文件中的父标签或任何包含标签上,包括根标签(Window
或UserControl
或ResourceDictionary
)。把它放在这里使这个例子更加独立。<HierarchicalDataTemplate xmlns:local="clr-namespace:YOUR_NAMESPACE_HERE" > <HierarchicalDataTemplate.Resources> <local:IntToStringConverter x:Key="IntToString" /> </HierarchicalDataTemplate.Resources> <!-- blah blah --> <TextBlock Text="{Binding XPath=UnitStrength, Converter={StaticResource IntToString}, ConverterParameter=N0}" />
更新
<Window.Resources>
<!-- stuff -->
<HierarchicalDataTemplate
x:Key="UnitTemplate"
ItemsSource="{Binding XPath=Unit}"
>
<Grid Width="auto">
<!-- stuff -->
</Grid>
</HierarchicalDataTemplate>
<!-- stuff -->
</Window.Resources>
对于 TreeView:
<TreeView
...
ItemTemplate="{StaticResource UnitTemplate}"
...
/>
但是如果一个模板只在一个地方使用,这也行得通:
<TreeView
...
>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate
ItemsSource="{Binding XPath=Unit}"
>
<Grid Width="auto">
<!-- stuff -->
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
另一个更新
或者最后,如果您想将所有数据模板放在它们自己的文件中,您想要创建一个资源字典:
<Window.Resources>
<!-- If you're doing the merged thing, you have to explicitly have the
ResourceDictionary tag here.
-->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="DataTemplates.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- other resources maybe -->
</ResourceDictionary>
</Window.Resources>
DataTemplate.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ScenarioEditor"
>
<local:IntToStringConverter
x:Key="IntToString"
/>
<HierarchicalDataTemplate
x:Key="UnitTemplate"
ItemsSource="{Binding XPath=Unit}"
>
<Grid Width="auto">
<!-- stuff -->
</Grid>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
x:Key="SomeOtherTemplate"
>
<Grid Width="auto">
<!-- different stuff -->
</Grid>
</HierarchicalDataTemplate>
</ResourceDictionary>
又一个更新
所以我们正在查看的树有多个级别,每个级别都有不同的模板。至少有两种方法可以做到这一点:如果我们有一个具有不同子类型的 .NET classes 树,我们可以在资源字典中定义 "implicit templates"。他们有一个 DataType
属性而不是 x:Key
,结果是(例如)带有 DataType="{x:Type local:HQ}"
的模板将自动用于显示该属性的任何 class 实例类型。
但是你有 XML 所以这行不通。你可以做的是给每个 HierarchicalDataTemplate
一个自己的 ItemTemplate
。为清楚起见,以下示例省略了 ItemsSource
和其他许多内容——它仅说明了我们如何设置那些 parent/child 模板关系。
<HierarchicalDataTemplate
x:Key="UnitTemplate"
>
<Grid>
<!-- Unit stuff -->
</Grid>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
x:Key="CommanderTemplate"
ItemTemplate="{StaticResource UnitTemplate}"
>
<Grid>
<!-- Commander stuff -->
</Grid>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
x:Key="HQTemplate"
ItemTemplate="{StaticResource CommanderTemplate}"
>
<Grid>
<!-- HQ stuff -->
</Grid>
</HierarchicalDataTemplate>
HQTemplate
将是树视图的 ItemTemplate
<TreeView
...
ItemTemplate="{StaticResource HQTemplate}"