2013-05-12 231 views
3

我想水平放置ItemControl中的項目,同時使他們填充父控件。WPF ItemsControl水平方向和填充父項?

這是我的XAML:

   <ItemsControl ItemsSource="{Binding AnnualWeatherViewModels}" Visibility="{Binding IsAnnualWeatherViewModels, Converter={StaticResource VisibilityConverter}}"> 
       <ItemsControl.ItemsPanel> 
        <ItemsPanelTemplate> 
         <StackPanel Orientation="Horizontal"></StackPanel> 
        </ItemsPanelTemplate> 
       </ItemsControl.ItemsPanel> 
       <ItemsControl.ItemTemplate> 
        <DataTemplate> 
         <V:AerosolSimpleWeatherCharacteristicsView DataContext="{Binding}"></V:AerosolSimpleWeatherCharacteristicsView> 
        </DataTemplate> 
       </ItemsControl.ItemTemplate> 
      </ItemsControl> 

兩個變化我已經嘗試了ItemsControl.ItemsPanel是:

<StackPanel Orientation="Horizontal"></StackPanel> 

和:

<DockPanel LastChildFill="False"></DockPanel> 

但是沒有達到預期的結果, StackPanel壓縮所有項目和DockPanel將e ither用專用於最後一項的大部分空間填充父控件的空間,或根據LastChildFill的值填充父空間。

那麼我該如何佈局我的ItemsControl的項目水平,並讓他們填寫家長控制的空間?

我結束了創建爲sugested在回答這個自定義控制:

public partial class StretchingPanel : Grid 
    { 
     public static readonly DependencyProperty OrientationProperty = 
      DependencyProperty.Register("Orientation", typeof(Orientation), typeof(StretchingPanel), new UIPropertyMetadata(System.Windows.Controls.Orientation.Horizontal)); 

     public static readonly DependencyProperty FillFirstItemProperty = 
      DependencyProperty.Register("FillFirstItem", typeof(bool), typeof(StretchingPanel), new UIPropertyMetadata(true)); 

     public static readonly DependencyProperty FillFirstItemFactorProperty = 
      DependencyProperty.Register("FillFirstItemFactor", typeof(double), typeof(StretchingPanel), new UIPropertyMetadata(1.8)); 

     public Orientation Orientation 
     { 
      get 
      { 
       return (Orientation)GetValue(OrientationProperty); 
      } 
      set 
      { 
       SetValue(OrientationProperty, value); 
      } 
     } 

     public bool FillFirstItem 
     { 
      get 
      { 
       return (bool)GetValue(FillFirstItemProperty); 
      } 
      set 
      { 
       SetValue(FillFirstItemProperty, value); 
      } 
     } 

     public double FillFirstItemFactor 
     { 
      get 
      { 
       return (double)GetValue(FillFirstItemFactorProperty); 
      } 
      set 
      { 
       SetValue(FillFirstItemFactorProperty, value); 
      } 
     } 

     protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved) 
     { 
      if (Orientation == System.Windows.Controls.Orientation.Horizontal) 
      { 
       ColumnDefinitions.Clear(); 
       for (int i = 0; i < Children.Count; ++i) 
       { 
        var column = new ColumnDefinition(); 
        if (i == 0 && FillFirstItem) 
         column.Width = new GridLength(FillFirstItemFactor, GridUnitType.Star); 
        ColumnDefinitions.Add(column); 
        Grid.SetColumn(Children[i], i); 
       } 
      } 
      else 
      { 
       RowDefinitions.Clear(); 
       for (int i = 0; i < Children.Count; ++i) 
       { 
        var row = new RowDefinition(); 
        if (i == 0 && FillFirstItem) 
         row.Height = new GridLength(FillFirstItemFactor, GridUnitType.Star); 
        RowDefinitions.Add(row); 
        Grid.SetRow(Children[i], i); 
       } 
      } 
      base.OnVisualChildrenChanged(visualAdded, visualRemoved); 
     } 

     public StretchingPanel() 
     { 
      InitializeComponent(); 
     } 
    } 
+0

屬性'的DataContext = 「{結合}」'是多餘的。去掉它。這與以下C#代碼有些相同:'this.DataContext = this.DataContext;' – 2013-05-12 22:36:35

+0

改用'/>'結束XAML元素也很方便。對於實例:''可以簡化爲'' – 2013-05-12 22:39:14

+0

感謝提示。 – 2013-05-12 22:45:32

回答

2

所以你想按比例拉伸項目。如果標準面板完全可以實現,則使用網格(可以有比例列),這需要在ItemSource更改後設置ColumnDefinitions。

這是一個自定義面板簡單:

class ProportionallyStretchingPanel : Panel 
{ 
    protected override Size MeasureOverride(Size availableSize) 
    { 
     foreach (UIElement child in InternalChildren) 
      child.Measure(availableSize); 
     return availableSize; 
    } 

    protected override Size ArrangeOverride(Size availableSize) 
    { 
     double widthSum = 0.0; 
     foreach (UIElement child in InternalChildren) 
     { 
      widthSum += child.DesiredSize.Width; 
     } 
     double x = 0.0; 
     foreach (UIElement child in InternalChildren) 
     { 
      double proportionalWidth = child.DesiredSize.Width/widthSum * availableSize.Width; 
      child.Arrange(
       new Rect(
        new Point(x, 0.0), 
        new Point(x + proportionalWidth, availableSize.Height))); 
      x += proportionalWidth; 
     } 
     return availableSize; 
    } 
} 

<ItemsPanelTemplate> 
    <local:ProportionallyStretchingPanel"/> 
</ItemsPanelTemplate> 
+0

你的權利唯一的方法就是創建一個自定義面板,所以我創建了一個網格,看到我更新的問題。 – 2013-05-15 03:47:00

8

UniformGrid做這項工作。

 <ItemsPanelTemplate> 
      <UniformGrid Rows="1"/> 
     </ItemsPanelTemplate> 
+0

被添加到ItemsControl中的控件大小不一樣,需要在每個控件的基礎上進行。 UniformGrid通過嘗試使它們全部大小相同,最終扭曲了所有內容。 – 2013-05-12 22:36:11

+0

只是想說這是我所需要的。我以前從來沒有聽說過UniformGrid,我覺得自己已經爲了一個簡單的解決方案而失去了很多可能性。謝謝! – 2016-11-17 00:38:37