2009-08-13 66 views
21

我正在嘗試編寫一個簡單的WPF學習項目,它在可調整大小的主窗口內創建一組按鈕。每個集合中的條目將有一個Button,並且該集合的內容在運行時可能會有所不同。我希望按鈕填滿整個窗口(例如,100%寬度的1個按鈕,寬度50%的2個按鈕,寬度33%的3個按鈕等)。什麼我至今寫一個簡化版本是:拉伸控件填充ItemsControl

<ItemsControl x:Name="itemscontrolButtons" ItemsSource="{Binding}"> 
    <ItemsControl.ItemTemplate> 
    <DataTemplate> 
     <Button Tag="{Binding}"> 
     <TextBlock Text="{Binding}" /> 
     </Button> 
    </DataTemplate> 
    </ItemsControl.ItemTemplate> 
    <ItemsControl.ItemsPanel> 
    <ItemsPanelTemplate> 
     <StackPanel Orientation="Horizontal" /> 
    </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
</ItemsControl> 
...  
List<string> listButtonTexts = new List<string>() { "Button1", "Button2" }; 
... 
itemscontrolButtons.DataContext = listButtonTexts; 

這導致了這個:

alt text

我已經無法使按鈕被拉伸以適應寬度和我的嘗試使用Grid而不是StackPanel是徒勞的。

然後,作爲一個可選的改進,我將不勝感激關於如何調整它的建議,以便如果有太多的按鈕,他們無法適合一條線或窄於閾值,它會包裝到一個新的線(如果從1行到2行,則將按鈕高度減半)。

我想強調一下,我想知道如何做到這一點WPF方式。我意識到我可以使用窗口大小調整消息並顯式調整控件的大小,這就是我如何使用MFC或WinForms完成的,但從我讀過的內容來看,並不是WPF應該如何完成這些操作。

回答

48

更換的項目控制的一個UniformGrid面板,這將大小所有的孩子,所以一切完全適合:

<ItemsControl> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <UniformGrid Rows="1"/> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
</ItemsControl> 
+0

這正是我需要的主要目標,謝謝。 – Gregyski 2009-08-13 15:07:23

+0

感謝Nir的回答,我能夠完成可選標準。詳情在我發佈到這個問題的答案中。在Meta上推薦我這樣處理這種情況。 http://meta.stackexchange.com/questions/14306/my-improved-answer-based-on-anothers-accepted-answer-for-my-own-question – Gregyski 2009-08-17 23:53:43

+0

謝謝!這正是我所缺少的將項目及其面板均勻分佈在列表框中的缺失。 – 2013-03-15 01:47:50

0
<!-- width must be explicitly set for this example --> 
<StackPanel 
    Name="MyStack" 
    Orientation="Horizontal" 
    Width="250" 
    Load="Window_Loaded"> 
    <Button/> 
    <Button/> 
    <Button/> 
</StackPanel> 

public void Window_Loaded(object sender, RoutedEventArgs e) 
{ 
    UIElementCollection elements = MyStack.Children; 
    int count = elements.Count; 

    foreach (UIElement element in elements) 
    { 
     if (element is Button) 
      ((Button)element).Width = MyStack.Width/count; 
    } 
} 
+0

我編輯我的帖子只有20分鐘之前,你迴應解釋說,我想避免明確設置寬度。對不起,我應該首先考慮包括這一要求。如果要使用WrapPanel,則可以根據我的第二要求明確地管理像這樣的維度(以及處理調整大小消息)。謝謝。 – Gregyski 2009-08-13 15:11:14

2

我是能夠建立在尼爾回答履行我的可選標準允許多行WPF管理拉伸。

首先你必須能夠改變模板的屬性UniformGrid。爲此,您需要存儲對其的引用。有multiple methods for accomplishing this。我選擇處理加載的事件UniformGrid並在那時存儲引用。

<ItemsControl ItemsSource="{Binding}"> 
    <ItemsControl.ItemsPanel> 
    <ItemsPanelTemplate> 
     <UniformGrid Rows="1" Loaded="UniformGrid_Loaded" /> 
    </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
</ItemsControl> 

而且在後面的代碼:

UniformGrid uniformgridButtons; 
private void UniformGrid_Loaded(object sender, RoutedEventArgs e) 
{ 
    uniformgridButtons = sender as UniformGrid; 
} 

然後,處理SizeChanged將事件,並根據您所希望的任何標準調整行參數。

private void Window_SizeChanged(object sender, SizeChangedEventArgs e) 
{ 
    if ((uniformgridButtons != null) && (this.Width > 0)) 
    { 
    // Set row count according to your requirements 
    uniformgridButtons.Rows = (int)(1 + ((this.MinWidth * iButtonCount)/this.Width)); 
    } 
} 

所以這使得WPF來管理尼爾回答拉伸一樣,但可以讓你明確調整的行數。上面的代碼給出了這樣的結果:

alt text

(動畫樣本here


更新2009/08/28:

我調整我的學習應用程序,以便ItemsControl在單獨的ResourceDictionary中位於DataTemplate中。但是,諸如Loaded的事件無法在外部ResourceDictionary XAML文件中處理,因爲它沒有代碼隱藏(通常)。因此,我需要使用不同的技術來緩存對UniformGrid的引用。我想用Alan Haigh's FindItemsPanel method (10th reply)。首先,我取代了ItemsControl有:

<ContentPresenter x:Name="contentpresenterButtons" Content="{Binding obscolButtons}" /> 

然後在我的ResourceDictionary,我把ItemsControlDataTemplate

<DataTemplate DataType="{x:Type local:Buttons}"> 
    <ItemsControl ... 
</DataTemplate> 

最後,我存儲的參考模板UniformGrid像這樣:

private void Window_Loaded(object sender, RoutedEventArgs e) { 
    uniformgridButtons = FindItemsPanel<UniformGrid>(contentpresenterButtons); 
    // Also call the code in Window_SizeChanged which I put in another method 
} 

這與我以前的解決方案一樣,但不需要0123中的事件處理程序。