分层模板格式化问题/问题

Hierarchical Template Formatting Problems / Questions

我有几个关于 TreeView 的分层模板格式的问题。此图片将说明:

这里是第三层的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>

在此先感谢您的帮助!

  1. 去掉 UnitName 标签上的固定高度。你有网格单元,你不想要固定的高度。该间隙的一部分可能是您字体的行高。暂时在标签上设置Background="LightSkyBlue",看看标签本身实际占用了多少space。

  2. 看起来图像上的 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 上查找一个 属性 花费的时间更少,但事实并非如此,因为第一种方法是总是保证完全浪费时间。这就像闭上眼睛开车,并试图根据撞到障碍物的感觉来控制方向。

  3. 您将正确的格式字符串分配给了错误的 属性。试试这个:

    <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 文件中的父标签或任何包含标签上,包括根标签(WindowUserControlResourceDictionary)。把它放在这里使这个例子更加独立。

    <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}"