2012-02-28 53 views
0

是否有某種方法可以將WPF多選ListBoxHeight屬性設置爲項高的倍數,類似於設置html select元素的size屬性?WPF列表框的高度可以設置爲其項目高度的倍數嗎?

我有業務需求有在列表的底部顯示一半的項目(如果它是一個長長的名單有滾動條),並在底部沒有多餘的空格(如果它是一個短名單與所有項目顯示),但我可以找到這樣做的唯一方法是保持調整Height,直到它看起來是正確的。我曾經問過同事們,搜索過MSDN和StackOverflow,做了一些Google搜索,看看VS Intellisense在編輯代碼時提供了什麼,有很多關於如何設置的建議適合ListBox的容器的高度,但這與我試圖做的是相反的。)

回答

7

是的,人們可以想象會有一個更簡單的方法來做到這一點(單snapToWholeElement屬性)。我也找不到這個屬性。

爲了達到您的要求,我寫了一點邏輯。基本上,在我的Windows對象中,我有一個公共屬性lbHeight它通過計算每個單獨項目的高度來計算列表框高度。

首先,讓我們來看看XAML:

<Window 
    x:Class="SO.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="120" SizeToContent="Height" 
    Title="SO Sample"  
    > 
    <StackPanel> 
     <ListBox x:Name="x_list" Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=lbHeight}" > 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <Border x:Name="x" Background="Gray" Margin="4" Padding="3"> 
         <TextBlock Text="{Binding}" /> 
        </Border> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
    </StackPanel>   
</Window> 

注意ItemTemplate中是有點不平凡。需要注意的一件重要事情是,我給這個項目一個名稱 - 所以我可以在以後找到它。

在代碼隱藏構造我把一些數據在列表框中:

public MainWindow() 
{ 
    InitializeComponent(); 
    this.x_list.ItemsSource = Enumerable.Range(0, 100); 
} 

下一個,我實現findVisualItem - 查找數據模板的根元素。我做了這個功能有點通用的,所以它得到了謂詞p其確定這是否是元素,我想找到:

private DependencyObject findVisualItem(DependencyObject el, Predicate<DependencyObject> p) 
{ 
    DependencyObject found = null; 

    if(p(el)) { 
     found = el; 
    } 
    else { 
     int count = VisualTreeHelper.GetChildrenCount(el); 
     for(int i=0; i<count; ++i) { 
      DependencyObject c = VisualTreeHelper.GetChild(el, i); 
      found = findVisualItem(c, p); 
      if(found != null) 
       break; 
     } 
    } 
    return found; 
} 

我將使用下面的謂詞,它返回如果真我正在尋找的元素是一個邊框,它的名字是「x」。您應修改此謂詞以匹配ItemTemplate的根元素。

findVisualItem(
    x_list, 
    el => { return (el is Border) ? ((FrameworkElement)el).Name == "x" : false; } 
    ); 

最後,lbHeight屬性:

public double lbHeight 
{ 
    get { 
     FrameworkElement item = findVisualItem( 
      x_list, 
      el => { return (el is Border) ? ((FrameworkElement)el).Name == "x" : false; } 
      ) as FrameworkElement; 
     if(item != null) { 
      double h = item.ActualHeight + item.Margin.Top + item.Margin.Bottom; 
      return h * 12; 
     } 
     else { 
      return 120; 
     } 
    } 
} 

,我也做了執行INotifyPropertyChanged的窗口,當加載列表框中的項目(加載列表框的事件),我開了的PropertyChanged 'lbHeight'屬性的事件。在某些時候,這是必要的,但在最後,當我已經有一個渲染項時,WPF獲取了lbHeight屬性。

有可能您的物品在高度上不一樣,在這種情況下,您必須將VirtualizedStackPanel中的所有物品相加。如果你有一個水平滾動條,你必須考慮它的總高度。但這是總體思路。自你發佈你的問題以來,只有3個小時 - 我希望有人會有一個更簡單的答案。

+0

感謝您的所有詳細信息:+1。 (但是,我會離開這一段時間,看看其他人是否有一些建議。) – nnnnnn 2012-02-28 12:04:58

1

這是通過將父級控制Height屬性設置爲Auto,而不將任何大小設置爲Listbox本身(或者也設置爲Auto)來完成的。 要限制列表大小,您還應該指定MaxHeight屬性

+0

感謝您的回答。不幸的是,自從我使用WPF的項目開始,我很久以前就已經開始工作了,而且我不再有工具來測試這個解決方案是否真正起作用,所以我不覺得我可以將其作爲公認的答案。 – nnnnnn 2013-06-28 21:41:46

相關問題