【问题标题】:A WPF ItemsControl and WrapPanel walk into a bar一个 WPF ItemsControl 和 WrapPanel 走进一个酒吧
【发布时间】:2015-09-22 20:56:11
【问题描述】:

我有一个ItemsControl,它在WrapPanel 中显示了一堆UserControl。这完美地工作,除非我有一堆用户控件,然后溢出呈现在屏幕外,我无法访问它。我的目标是让 WrapPanel 水平换行,但是一旦控件离开屏幕,就会显示一个滚动条,这似乎对我不起作用。

<ItemsControl ItemsSource="{Binding Servers, Mode=OneWay}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="Black" BorderThickness="1" Margin="5,5,5,5">
                <local:ServerControl DataContext="{Binding }" /> <!-- The actual UserControl -->
            </Border>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

当应用程序第一次启动时,这就是它的样子。如果应该查看 14 个框,您看不到什么。 WrapPanel 正在完成它的工作,但它呈现在窗口边界之外。

这显示了所有的用户控件,但我必须展开窗口才能看到它们。

任何帮助将不胜感激。

完整的 XAML:

<Window x:Class="ServerMonitor.Wpf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ServerMonitor.Wpf"
        xmlns:models="clr-namespace:ServerMonitor.Wpf.Models"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
        Title="Leading Hedge Server Monitor" Height="350" Width="800">
    <Window.DataContext>
        <models:MainWindowViewModel>
            <models:MainWindowViewModel.MachineNames>
                <!-- Test Servers -->
                <System:String>T009</System:String>
                <System:String>T010</System:String>
                <System:String>T011</System:String>
                <System:String>T012</System:String>
            </models:MainWindowViewModel.MachineNames>
        </models:MainWindowViewModel>
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Menu Grid.Row="0">

        </Menu>

        <ItemsControl Grid.Row="1" ItemsSource="{Binding Servers, Mode=OneWay}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Black" BorderThickness="1" Margin="5,5,5,5">
                        <local:ServerControl DataContext="{Binding }" />
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.Template>
                <ControlTemplate TargetType="{x:Type ItemsControl}">
                    <ScrollViewer VerticalScrollBarVisibility="Auto">
                        <ItemsPresenter />
                    </ScrollViewer>
                </ControlTemplate>
            </ItemsControl.Template>
        </ItemsControl>

    </Grid>
</Window>

【问题讨论】:

  • 我不确定您期望的实际行为 - 也许您可以详细说明您想要什么?如果您将换行面板放在滚动查看器中,那么它将不再作为换行面板工作,因为滚动查看器具有无限维度。在这种情况下,您不妨只使用堆栈面板。再说一次,告诉我你想要什么,我可能会给你一些想法/建议。 :)
  • 抱歉,我们的目标是让控件像环绕面板一样环绕,但如果控件环绕在窗口本身的边界之外,则激活滚动条,因此我不需要调整整个窗口本身可以看到一切。
  • 那么,你想水平换行,但是当它到达底部时你想垂直滚动?
  • 正确!这就是我想要完成的。显然,我的挫败感阻碍了我的词汇量。 :)
  • 在那种情况下,我认为 Moises 答案的后半部分就是你想要的。

标签: c# wpf scrollviewer itemscontrol wrappanel


【解决方案1】:
<ItemsControl ItemsSource="{Binding Servers, Mode=OneWay}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="Black" BorderThickness="1" Margin="5,5,5,5">
                <local:ServerControl DataContext="{Binding }" /> <!-- The actual UserControl -->
            </Border>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.Template>
        <ControlTemplate TargetType="{x:Type ItemsControl}">
            <ScrollViewer VerticalScrollBarVisibility="Auto">
                <ItemsPresenter />
            </ScrollViewer>
        </ControlTemplate>
    </ItemsControl.Template>
</ItemsControl>

<ScrollViewer VerticalScrollBarVisibility="Auto">
  <ItemsControl ItemsSource="{Binding Servers, Mode=OneWay}">
     ...
  <ItemsControl/>
</ScrollViewer>

【讨论】:

  • @DanChampagne 这个答案的第一部分没有意义,但第二部分应该可以工作。尝试删除您的 local:ServerControl 并给边框一个固定的宽度和高度。它真的应该可以工作 - 我已经复制并粘贴了您的代码,注释掉了 ServerControl,放入了 ScrollViewer,它确实可以工作......
  • @user3690202 我在帖子中添加了几张照片以显示我所看到的。这些建议实际上都没有给我我所追求的行为。两者都要求我展开窗口,而不是给我一个可用的 ScrollBar。
  • 这是问题所在:
【解决方案2】:

将您的第二行高度更改为*

<Grid.RowDefinitions>
   <RowDefinition Height="Auto" />
   <RowDefinition Height="*" /> <-- This is what you want -->
   <RowDefinition Height="Auto" />
   <RowDefinition Height="Auto" />
</Grid.RowDefinitions>

RowDefinition 设置为Auto 意味着它将计算该行中所有子元素的累积DesiredHeight,并将其分配给RowDefinitionHeight 属性。因此,随着您的 WrapPanel 增长,它会将高度应用于该行并伸展您的父级 Grid

【讨论】:

  • 我仍然认为更清洁的方法是将滚动查看器放在网格之外并将该行保留为自动 - 但无论您的船是否漂浮
  • 你也需要 ScrollViewer。
猜你喜欢
  • 2019-05-09
  • 2011-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-05
相关资源
最近更新 更多