2010-05-03 63 views
1

我有一個WPF應用程序,它具有ViewBox以顯示我的集合中的項目,爲我的結果提供了2列網格。WPF:根據數據量更改ViewBox的樣式

我想要做的是,根據我的收藏中的物品數量,更改列數。例如,如果列表中有10個項目,然後僅顯示1列;如果我的列表中有10個項目,則將它們顯示在2列中;如果我的列表中有20個項目,則顯示3列。

這裏是我目前:

<Viewbox> 
    <ItemsControl ItemsSource="{Binding myCollection}" Style="{DynamicResource myStyle}" /> 
</Viewbox> 

這裏是myStyle的目前定義:

<Style x:Key="myStyle" TargetType="{x:Type ItemsControl}"> 
    <Setter Property=ItemsControl.ItemsPanel"> 
     <Setter.Value> 
     <ItemsPanelTemplate> 
      <UniformGrid Columns="2" /> 
     </ItemsPanelTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

我怎樣才能讓這段代碼工作,上述要求?謝謝。

回答

2

您可以在Columns屬性綁定到項目的數量和使用適當的IValueConverter確定的列數,像這樣:

<UniformGrid Columns="{Binding Items.Count, Converter={local:ItemsToColumnConverter}}" /> 

請注意,您可能需要一個的RelativeSource增加這個綁定爲了使它工作。

而一個的IValueConverter類似於:

public class ItemsToColumnConverter : IValueConverter 
{ 
    // ... 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     int numItems = (int)value; 
     if (numItems < 10) 
      return 1; 
     else if (numItems < 20) 
      return 2; 
     else if (numItems < 30) 
      return 3; 
     else 
      return numItems/10; 
    } 

    public object ConvertBack(...) 
    { 
     throw new NotSupportedException(); 
    } 
} 

當然,你也可以使該轉換器的使用避免了所有的IF-ELSEIF-ELSE東西另一個數學邏輯。

+0

+1。很好,很乾淨。 – Gishu 2010-05-03 14:40:41

+0

如果其他WPF noobs看到這個代碼,請注意它不會按原樣編譯(至少對我而言)。我必須在轉換器類中添加一個'ValueConversion'屬性,創建一個該類型的靜態資源,然後設置'Converter = {StaticResource myConverter}'。也許我錯過了一些東西,但那很奏效。 – Pat 2010-08-27 20:56:21

+0

只是爲了澄清事情:1)你不需要聲明'StaticResource'。只需指定您的轉換器所在的命名空間爲「xmlns:local」,並如上所示使用它:'Converter = {local:ItemsToColumnConverter}'。 2)'ValueConversion'屬性不是必需的。從[MSDN](http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx):*「...這是一個很好的做法,用ValueConversionAttribute來修飾實現。 ..「*這並不妨礙代碼編譯。它是'ConvertBack(...)'方法的定義不完整(只是一個例子!)。 – gehho 2010-08-30 06:26:06

1

如何使用DataTrigger設置特定的樣式?如果你有少量'如果大小然後列'元組可能是可行的。
我看到沒有ItemsPanelStyleSelector等價物(類似於ItemContainerStyleSelector)。

更新:它的工作原理。儘管我也會看看其他的迴應。使用valueconverter將Columns值綁定到ValueConverter.Convert(list.Count)返回的值 - 聽起來更乾淨。

public string[] Options { get; set;} 

    public bool NeedsTwoColumns 
    { 
     get 
     { 
      return this.Options.Length > 4; 
     } 
    } 

//Xaml 
<ListBox ItemsSource="{Binding Options}"> 
      <ListBox.Style> 
       <Style> 
        <Style.Triggers> 
         <DataTrigger Binding="{Binding NeedsTwoColumns}" Value="True"> 
          <Setter Property="ItemsControl.ItemsPanel"> 
           <Setter.Value> 
            <ItemsPanelTemplate> 
             <UniformGrid Columns="2"/> 
            </ItemsPanelTemplate> 
           </Setter.Value> 
          </Setter> 
         </DataTrigger> 
        </Style.Triggers> 
       </Style> 
      </ListBox.Style> 
     </ListBox> 
    <ListBox ItemsSource="{Binding Options}"> 
     <ListBox.Resources> 
      <local:MyConverter x:Key="ListLengthToColumnCountConverter"/> 
     </ListBox.Resources> 
     <ListBox.ItemsPanel> 
      <ItemsPanelTemplate> 
       <UniformGrid Columns="{Binding Options.Length, Converter={StaticResource ListLengthToColumnCountConverter}}"/> 
      </ItemsPanelTemplate> 
     </ListBox.ItemsPanel> 
    </ListBox> 

//ValueConverter 
public class MyConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     int listSize = (int)value; 
     return (int)(listSize/3); 
    } ... 
+0

好吧,聽起來不錯...這是如何工作的? – 2010-05-03 13:21:38

+0

@Brett - 查看更新。我喜歡使用ValueConverter的方法......不夠詳細和可維護。 – Gishu 2010-05-03 14:40:19