1

次の定義を持つ 3 つの列を持つグリッドで構成されるTreeViewItems があります。HierarchicalDataTemplate

<Grid>    
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="1*" />
    <ColumnDefinition Width="Auto" />
...

TreeViewItem内部の利用可能なすべてのスペースを正確に占めるように、グリッドの幅を設定したいと思いますTreeView。したがって、グリッドの 3 番目の列は、 内で右揃えにする必要がありますTreeView

グリッドの幅の正しい値を取得するにはどうすればよいですか?

ListBox ItemTemplateの場合、次のようにバインドして幅を設定できることを知っていScrollContentPresenterます。

Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ScrollContentPresenter, AncestorLevel=1}, Path=ActualWidth}"

TreeViewルート ツリービュー アイテムよりも子が利用できるスペースが少ないため、このトリックは では機能しません。

何か案は?

4

3 に答える 3

7

数時間作業した後、Multibinding2 つの Convertersを使用して実用的なソリューションを見つけました。

まず、HierarchicalDataTemplateXAML での定義:

<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 の最初のバインディングは、ScrollContentPresenterinの幅を取得します。TreeViewこれは、 の表示可能な幅の合計TreeViewです。2 番目のバインディングは、 を引数としてコンバーターを呼び出し、ルート アイテムに到達する前に、 が持つTreeViewItem親の数を計算します。TreeViewItemこれら 2 つの入力を使用して、SumConverterInstance を使用して、指定されMultibindingた の使用可能な幅を計算しますTreeViewItem

XAML で定義されているコンバーター インスタンスは次のとおりです。

  <my:SumConverter x:Key="SumConverterInstance" />
  <my:ParentCountConverter x:Key="ParentCountConverterInstance" />

および 2 つのコンバーターのコード:

// 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();
    }
}

これで正しい外観になりました。

代替テキスト

于 2010-07-15T13:38:29.703 に答える
1

で固定幅を強制するのではなく、レイアウト システムにこれを処理させる必要がありますItemTemplate。の場合はListBox、設定するだけですHorizontalContentAlignment="Stretch"。これも最初のステップですTreeViewが、残念ながら、デフォルトのテンプレートには追加の変更が必要なレイアウトがいくつかあります。コンテンツを 2 列目に配置し、子のみを 3 列目 (*) に拡張する 3 列のグリッドを使用します。Grid.ColumnSpan="2"ContentPresenter含むにを追加するBorderと、コンテンツはアイテムの領域全体に広がります。

<PathGeometry x:Key="TreeArrow" Figures="M0,0 L0,6 L6,0 z"/>
<Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
    <Setter Property="Focusable" Value="False"/>
    <Setter Property="Width" Value="16"/>
    <Setter Property="Height" Value="16"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Border Background="Transparent" Height="16" Padding="5,5,5,5" Width="16">
                    <Path x:Name="ExpandPath" Data="{StaticResource TreeArrow}" Fill="Transparent" Stroke="#FF989898">
                        <Path.RenderTransform>
                            <RotateTransform Angle="135" CenterY="3" CenterX="3"/>
                        </Path.RenderTransform>
                    </Path>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF1BBBFA"/>
                        <Setter Property="Fill" TargetName="ExpandPath" Value="Transparent"/>
                    </Trigger>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter Property="RenderTransform" TargetName="ExpandPath">
                            <Setter.Value>
                                <RotateTransform Angle="180" CenterY="3" CenterX="3"/>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Fill" TargetName="ExpandPath" Value="#FF595959"/>
                        <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF262626"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<ControlTemplate TargetType="{x:Type TreeViewItem}">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition MinWidth="19" Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <ToggleButton x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}"/>
        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"
                Grid.Column="1" Grid.ColumnSpan="2" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
            <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
        </Border>
        <ItemsPresenter x:Name="ItemsHost" Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1"/>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="IsExpanded" Value="false">
            <Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
        </Trigger>
        <Trigger Property="HasItems" Value="false">
            <Setter Property="Visibility" TargetName="Expander" Value="Hidden"/>
        </Trigger>
        <Trigger Property="IsSelected" Value="true">
            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
        </Trigger>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsSelected" Value="true"/>
                <Condition Property="IsSelectionActive" Value="false"/>
            </MultiTrigger.Conditions>
            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        </MultiTrigger>
        <Trigger Property="IsEnabled" Value="false">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
于 2010-07-13T21:20:37.303 に答える
0

あなたが説明しているTreeViewのはItemContainerStyleであり、上で説明しているグリッドは ですHierarchicalDataTemplate

TreeViewはメールの添付ファイルを表示しています。TreeViewItemには、アイコン (グリッドの最初の列)、ファイル名とサイズ (2 番目の列)、および時間 (3 番目の列) が含まれます。TreeView. _

以下は、動作しない例です。ご覧のとおり、ファイル名がラップされていないため、一部のアイテムの日付を確認できません。

代替テキスト

于 2010-07-15T06:05:25.900 に答える