2012-02-28 5 views
0

WPFマルチセレクトListBoxHeight属性を項目の高さの倍数に設定する方法はありますか?select要素のsize属性を設定するのと同様ですか?WPF ListBoxの高さをアイテムの高さの倍数に設定できますか?

私はないにビジネス要件は(それがスクロールバーとの長いリストの場合)、リストの一番下に示す半アイテムを持っている、そしてそれは短いリストだ場合(一番下に余分な空白を持っていませんすべてのアイテムが表示されます)、これを行うために私が見つけることができる唯一の方法は、正しく表示されるまでHeightを調整しておくことです。

(私は同僚に尋ね、MSDNとStackOverflowを検索し、一般的なグーグルを行って、VS Intellisenseが提供したコードを見てみました。 ListBoxのコンテナに合う高さですが、それは私がやろうとしているのと反対です)。

答えて

7

これは簡単な方法です(単一のsnapToWholeElementプロパティ)。私はこのプロパティも見つけられませんでした。

あなたの要件を達成するために、私は少しの論理を書いています。基本的には、私のWindowsオブジェクトでは、私は公共のプロパティlbHeightを持っています。個々の項目の高さを計算してリストボックスの高さを計算します。

まずは、XAMLを見てみましょう:ItemTemplateにはやや非自明であることを

<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> 

注意。注目すべき重要なことは、私がこのアイテムに名前を与えたことです。後で見つけることができます。コードビハインドコンストラクタ私はリストボックスにいくつかのデータを入れて

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

を次は、私がfindVisualItemを実装しています - データテンプレートのルート要素を見つけること。

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; 
} 

場合、私がtrueを返し、次の述語を、使用します:それは、これは私が見つけたい要素であるかどうかを識別する述語Pを取得するので、私は、この関数は少しジェネリック作りました私が探している要素は境界線であり、その名前は "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; 
     } 
    } 
} 

私はにPropertyChangedを解雇(ListBoxコントロールのLoadedイベント)INotifyPropertyChangedのを実装するウィンドウをも作ったし、リストボックスの項目がロードされたとき'lbHeight'プロパティのイベントです。ある時点では必要でしたが、最後にWPFはレンダリングされたItemを持っているときにlbHeightプロパティを取得しました。

あなたのアイテムが高さで同一ではない可能性があります。その場合、VirtualizedStackPanel内のすべてのアイテムを合計する必要があります。水平スクロールバーを使用している場合は、コース全体の高さを考慮する必要があります。しかし、これは全体的なアイデアです。あなたの質問を公表してからわずか3時間です。誰かがより簡単な答えを得ることを願っています。

+0

ありがとうございます。 (しかし、はい、私は誰かがいくつかの提案をしているかどうかを確認するためにこれをしばらく残します) – nnnnnn

1

これは、親コントロールHeightのプロパティをAutoに設定し、リストボックス自体にサイズを設定せずに(またはAutoに設定しても)行われます。 リストサイズを制限するには、MaxHeightプロパティも指定してください。

+0

この答えをありがとう。残念ながら、私はWPFを使用していたプロジェクトからずっと前に移りました。このソリューションが実際に動作するかどうかをテストするツールがなくなったので、私はそれを受け入れられる回答にすることができません。 – nnnnnn

関連する問題