2013-02-08 13 views
2

我有一個自定義控件ListBox,我想根據其ItemsPanel的大小調整它的大小。對於項目面板,我有一個自定義控件WrapPanel來相應地排列項目。正如你可以在屏幕截圖中看到的,ListBox更喜歡將自己的大小設置爲其父控件或availableSize。使ListBox大小適合用作ItemsPresenter的ItemsPanel

所以然後我試圖做一個自定義控件網格,它有一個ItemsSource屬性把項目交給它的列表框。但是那也行不通。當網格將安排,然後列表框將安排,這將導致網格排列等。

所以我的問題是,如何創建一個具有ItemsSource屬性和ItemsPresenter的自定義控件,該控件根據其子對象的大小自行調整大小?

Screenshot of ListBox Custom Control

回答

1

這是我必須做的就是我想要的功能。首先,我必須創建我的SquareWrapPanel。這就是魔法發生的地方,並按我想要的方式排列我的物品。

protected override Size ArrangeOverride(Size finalSize) 
    { 
     return ArrangeByChildCount(finalSize); 
    } 

    private Size ArrangeByChildCount(Size finalSize) 
    { 

     double childWidth = 0; 
     double childHeight = 0; 


     foreach (UIElement e in Children) 
     { 
      e.Measure(finalSize); 

      childWidth = e.DesiredSize.Width; 
      childHeight = e.DesiredSize.Height; 
     } 

     if (Children.Count > 0) 
     { 
      int square = (int)Math.Sqrt(Children.Count); 


      int rowCount = square + Children.Count % square; 
      int columnCount = square; 

      double height = rowCount * childHeight; 
      double width = columnCount * childWidth; 

      Size size = new Size(width, height); 
      base.ArrangeOverride(size); 
      return size; 
     } 
     else 
     { 
      return new Size(300, 300); 
     } 
    } 

然後我創建了一個擴展ItemsControl的自定義面板。這樣我可以將一系列項目綁定到它。代碼中沒有任何內容,但這是我必須使用的樣式。

<Style TargetType="{x:Type local:SquareItemsPanel}" BasedOn="{StaticResource {x:Type ItemsControl}}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="ItemsControl"> 
       <Border BorderBrush="Black" BorderThickness="2" CornerRadius="4"> 
        <Expander x:Name="exp" Header="View"> 
         <local:SquareWrapPanel IsItemsHost="True"/> 
        </Expander> 
       </Border> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 
1

你只需要設置你的ListBox的Horizo​​ntalAlignment至左VerticalAlignment頂部。這應該做的伎倆。

簡單的例子:

MainWindow.xaml

<Window x:Class="ListBoxFitItemsPanel.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="400" Width="400"> 
    <ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" Background="Red" HorizontalAlignment="Left" VerticalAlignment="Top" > 
     <ListBox.ItemsPanel> 
      <ItemsPanelTemplate> 
       <WrapPanel Background="AntiqueWhite" Margin="5" /> 
      </ItemsPanelTemplate> 
     </ListBox.ItemsPanel> 

     <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" /> 
     <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" /> 
     <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" /> 
     <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" /> 
     <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" /> 
     <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" /> 
     <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" /> 
     <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" /> 
     <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" /> 
    </ListBox> 
</Window> 

enter image description here

編輯:它也可以在綁定方案:

MainWindow.xaml

<Window x:Class="ListBoxFitItemsPanel.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:ListBoxFitItemsPanel" 
     Title="MainWindow" Height="400" Width="400"> 
    <Window.Resources> 
     <DataTemplate DataType="{x:Type local:Item}"> 
      <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" /> 
     </DataTemplate> 
    </Window.Resources> 
    <ListBox ItemsSource="{Binding Items}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" Background="Red" HorizontalAlignment="Left" VerticalAlignment="Top" > 
     <ListBox.ItemsPanel> 
      <ItemsPanelTemplate> 
       <WrapPanel Background="AntiqueWhite" Margin="5" /> 
      </ItemsPanelTemplate> 
     </ListBox.ItemsPanel> 
    </ListBox> 
</Window> 

MainWindow.xaml.cs

using System.Collections.Generic; 
using System.Windows; 

namespace ListBoxFitItemsPanel 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      DataContext = this; 
     } 

     public IEnumerable<Item> Items 
     { 
      get 
      { 
       for (int i = 0; i < 9; i++) 
       { 
        yield return new Item(); 
       } 
      } 
     } 
    } 

    public class Item { } 
} 
+0

這並不是退出它。你看,ListBox仍然安排在窗口內。然後WrapPanel安排它的孩子。我想要的是ListBox能很好地適應其自己的ItemsPanel,它已經確定了它的大小。 – 2013-02-08 16:07:10

+0

+1這是正確的答案。 'ListBox'正在填充它的容器面板。您需要通過使用「Horizo​​ntalAlignment」和「VerticalAlignment」使其在其父級中對齊。 – 2013-02-08 16:10:07

+0

@Jesse:在這種情況下,它不會。雙重佈局通過基於所有兒童返回的大小來測量和排列頂部容器。在我發佈的屏幕截圖中,窗口背景爲白色,而列表框背景爲紅色。我設置了一個邊距以使其可見。您可以看到ListBox只佔用了換行符所需的空間。如果您嘗試修復包裝面板的高度或寬度,則ListBox不會佔用更多。 – Sisyphe 2013-02-08 16:12:11

相關問題