2010-07-13 44 views
1

我有TreeViewItem爲什麼會產生HierarchicalDataTemplate由3列,分別定義一個網格內:如何獲得樹型視圖的可用(可視)的寬度一個TreeView

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

我想設置的寬度的網格,因此它將佔用TreeView內的TreeViewItem的所有可用空間。網格的第三列因此應該在TreeView內右對齊。

如何獲得正確的網格寬度值?

我知道,對於ListBoxItemTemplate,我可以通過它綁定到ScrollContentPresenter設置寬度:

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

這招不TreeView工作,因爲孩子有十幾根樹視圖可用空間少項目。

任何想法?

回答

6

它的工作了幾個小時後,我發現使用Multibinding兩個轉換器一個可行的解決方案。

首先,在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結合獲取ScrollContentPresenterTreeView寬度,這是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(); 
    } 
} 

現在,這是正確的樣子:

alt text http://img249.imageshack.us/img249/6889/atts2.png

+0

感謝此代碼。這適用於我! 乾杯! – klaydze 2015-09-28 00:37:21

+0

完美適合我:) – 2015-10-25 11:40:05

1

您應該讓佈局系統爲您處理這個問題,而不是在您的ItemTemplate中強制固定寬度。對於ListBox,您所需要做的就是設置HorizontalContentAlignment="Stretch"。這也是TreeView的第一步,但不幸的是,默認模板中還有一些其他佈局需要額外的更改。它使用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> 
+0

謝謝你的回答約翰,但不幸的是這不是我的問題的答案。我正在描述爲什麼在底部帖子中,因爲評論的大小是有限的...... – 2010-07-15 06:06:29

+0

您正在使用的DataTemplate用於填充TreeViewItem模板中的ContentPresenter,因此您可以在DataTemplate內部執行的操作受限於佈局ControlTemplate中的ContentPresenter和ItemsPresenter。例如,如果ControlTemplate爲其根網格指定寬度爲0,則無論您在DataTemplate中做什麼,都不會顯示出來。嘗試在Snoop中檢查您的佈局(寬度,高度和路線)以更好地理解問題。 – 2010-07-15 12:41:16

0

你所描述的是TreeViewItemContainerStyle,我上面描述的網格是HierarchicalDataTemplate

在我的TreeView中顯示電子郵件附件。其中包含一個圖標(網格的第一列),文件名和大小(第二列)和時間(第三列)。我希望根據TreeView的寬度看到項目被拉伸或擠壓(通過包裝網格的中間列)。

下面是一個不起作用的例子。正如你所看到的文件名不被包裝,所以你不能看到一些項目的日期。

alt text http://img638.imageshack.us/img638/1743/attsv.png

相關問題