[英]Stretching controls to fill ItemsControl
我正在嘗試編寫一個簡單的WPF學習項目,該項目在可調整大小的主窗口內創建一組按鈕。 集合中的每個條目都有一個Button
,並且該集合的內容在運行時可能會有所不同。 我希望按鈕能夠填滿整個窗口(例如1個按鈕@ 100%寬度,2個按鈕@ 50%寬度,3個按鈕@ 33%寬度等等都在100%高度)。 我到目前為止所編寫的簡化版本是:
<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;
這導致:
我無法使按鈕拉伸以適應寬度,我嘗試使用Grid
而不是StackPanel
是徒勞的。
然后,作為一個可選的改進,我將很感激如何調整它的建議,如果有這么多的按鈕,他們不能正確地適合在一條線上或比一個閾值窄,它將包裹到一個新的線(從而減半按鈕高度,如果從1到2行)。
我想強調一下,我想知道如何以WPF的方式做到這一點 。 我意識到我可以使用窗口調整大小的消息並顯式調整控件的大小,這就是我用MFC或WinForms完成它的方式,但從我讀過的內容並不是如何用WPF完成的。
將項目控件的面板替換為UniformGrid,這將調整所有子項的大小,以便所有內容完全適合:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
我能夠建立在Nir的答案上,以實現我的可選標准,允許WPF管理的多行拉伸。
首先,您必須能夠更改模板UniformGrid的屬性。 為此,您需要存儲對它的引用。 有多種方法可以實現這一點 。 我選擇處理UniformGrid的Loaded事件並在那時存儲引用。
<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事件並根據您希望的任何條件調整rows參數。
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像Nir的答案一樣管理拉伸,但允許您明確調整行數。 上面的代碼給出了這個結果:
( 這里的動畫樣本)
更新2009/08/28:
我正在調整我的學習應用程序,以便ItemsControl
在一個單獨的ResourceDictionary
中的DataTemplate
中。 但是,諸如Loaded
事件無法在外部ResourceDictionary
XAML文件中處理,因為它沒有代碼隱藏(通常)。 因此,我需要使用不同的技術緩存對UniformGrid
的引用。
我使用了Alan Haigh的FindItemsPanel
方法(第10個回復) 。 首先,我將ItemsControl
替換為:
<ContentPresenter x:Name="contentpresenterButtons" Content="{Binding obscolButtons}" />
然后在我的ResourceDictionary
,我將ItemsControl
放在DataTemplate
:
<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
}
這與我之前的解決方案一樣,但不需要ResourceDictionary
的事件處理程序。
<!-- 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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.