.net 拉伸控件以填充项目控件

.net 拉伸控件以填充项目控件,.net,wpf,xaml,itemscontrol,.net,Wpf,Xaml,Itemscontrol,我试图写一个简单的WPF学习项目,在一个可调整大小的主窗口中创建一组按钮。集合中的每个条目都有一个按钮,该集合的内容在运行时可能会有所不同。我想让按钮填满整个窗口(例如,100%宽度时有1个按钮,50%宽度时有2个按钮,33%宽度时有3个按钮,等等,所有按钮都在100%高度)。到目前为止,我所写内容的简化版本是: <ItemsControl x:Name="itemscontrolButtons" ItemsSource="{Binding}"> <ItemsControl

我试图写一个简单的WPF学习项目,在一个可调整大小的主窗口中创建一组按钮。集合中的每个条目都有一个
按钮
,该集合的内容在运行时可能会有所不同。我想让按钮填满整个窗口(例如,100%宽度时有1个按钮,50%宽度时有2个按钮,33%宽度时有3个按钮,等等,所有按钮都在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;

...    
List listbuttonexts=新列表(){“Button1”、“Button2”};
...
itemscontrolButtons.DataContext=ListButtonText;
这导致:

我无法使按钮拉伸以适应宽度,并且我尝试使用
网格
而不是
堆栈面板
都是徒劳的

然后,作为一个可选的改进,我希望您能提出一些建议,说明如何调整它,以便在一行中有太多按钮无法正确安装或小于阈值时,它将换行(因此,如果从1行到2行,则将按钮高度减半)


我想强调的是,我想知道如何用WPF的方式来做这件事。我意识到我可以使用窗口调整消息并显式调整控件大小,这是我使用MFC或WinForms时应该做的事情,但从我所读到的内容来看,这不是使用WPF应该做的事情。

用UniformGrid替换项控件的面板,这将调整所有子项的大小,使所有子项都完全适合:

<!-- width must be explicitly set for this example -->
<StackPanel 
    Name="MyStack" 
    Orientation="Horizontal"
    Width="250"
    Load="Window_Loaded"> 
    <Button/>
    <Button/>
    <Button/>
</StackPanel>
<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Rows="1"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

我能够基于Nir的答案来满足我的可选标准,允许WPF管理多行拉伸

首先,您必须能够更改模板UniformGrid的属性。为此,您需要存储对它的引用。有。我选择处理UniformGrid的已加载事件,并在当时存储一个引用

<ItemsControl ItemsSource="{Binding}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <UniformGrid Rows="1" Loaded="UniformGrid_Loaded" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
</ItemsControl>
然后,处理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
中。但是,无法在外部
ResourceDictionary
XAML文件中处理
Loaded
之类的事件,因为它没有代码隐藏(通常)。因此,我需要使用不同的技术缓存对
UniformGrid
的引用

我改用了。首先,我将
ItemsControl
替换为:

<ContentPresenter x:Name="contentpresenterButtons" Content="{Binding obscolButtons}" />
最后,我将对模板化的
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
}
private void Window\u已加载(对象发送方,路由目标){
uniformgridButtons=FindItemsPanel(contentpresenterButtons);
//还可以调用我放在另一个方法中的Window_sizechange中的代码
}

这与我以前的解决方案的工作原理相同,但不需要在
ResourceDictionary

中使用事件处理程序。我仅在20分钟前编辑了我的文章,然后您回答说我希望避免显式设置宽度。很抱歉,一开始我本应该考虑包括这个要求。如果要使用WrapPanel,那么像这样显式地管理维度(以及通过处理调整大小消息)可能是我的第二个需求所必需的。谢谢。感谢Nir的回答,我能够满足可选标准。详细信息见我对这个问题的回答。Meta建议我以这种方式处理这种情况。谢谢这正是我在列表框中平均间隔项目及其面板所缺少的。
<ContentPresenter x:Name="contentpresenterButtons" Content="{Binding obscolButtons}" />
<DataTemplate DataType="{x:Type local:Buttons}">
  <ItemsControl ... 
</DataTemplate>
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
}