扩展器内的垂直 WrapPanel;我无法在窗口底部换行
我正在开发几年前构建的 WPF 项目。
一个控件是扩展控件,它将检查控件列表分组。
此检查控件列表由 WrapPanel 从左到右、从上到下排列!
现在我的目标是从上到下、从左到右排列检查控件,其中垂直换行发生在父窗口的底部!任何有关如何实现这一目标的提示/指示都非常棒!!
我已在代码示例中提取了该问题以突出显示该问题。
示例的行为: 该代码示例将 WrapPanel 的方向设置为水平。这是为了向您展示我想要实现什么样的行为! 换行在父窗口的右侧中断,并开始新的一行。当检查控件溢出屏幕底部时,会出现垂直滚动条。
我想实现的行为: 当到达父窗口的底部时(当包装面板设置为垂直方向时),我希望包装打破并再次从顶部开始。当检查控件溢出窗口的右侧时,我希望出现水平滚动条。
示例: 在代码中:将 Wrappanel 的 Orientation 属性更改为 Vertical。请注意,只有一列一直向下溢出,窗口底部没有换行! 因为我不确定如何附加 zip 文件(带有演示项目),所以我添加了下面的代码文件。 创建 WPF 应用程序 (.net Framework 3.5) 并将代码复制到正确的位置即可。 如果您在运行示例时遇到问题,我可以随时向您邮寄 VS2010 解决方案!
名为 VerticalWrapPanel 的项目
UserControl CheckControl.xaml
<UserControl x:Class="VerticalWrapPanel.CheckControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Border BorderThickness="1,1,1,1" BorderBrush="Black">
<Label Content="{Binding Label}"/>
</Border>
</UserControl>
UserControl CheckGroupControl.xaml
<UserControl x:Class="VerticalWrapPanel.CheckGroupControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:VerticalWrapPanel"
x:Name="GroupControl">
<UserControl.Resources>
<DataTemplate x:Key="CheckTemplate">
<controls:CheckControl />
</DataTemplate>
</UserControl.Resources>
<Expander BorderBrush="Black" Header="TEST" IsExpanded="{Binding ElementName=GroupControl, Path=IsExpanded}">
<ItemsControl ItemsSource="{Binding Checks}" ItemTemplate="{StaticResource CheckTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Expander>
</UserControl>
CheckGroupControl.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace VerticalWrapPanel
{
/// <summary>
/// Interaction logic for CheckGroupControl.xaml
/// </summary>
public partial class CheckGroupControl : UserControl
{
public CheckGroupControl()
{
InitializeComponent();
}
public static DependencyProperty IsExpandedProperty = DependencyProperty.Register("IsExpanded", typeof(bool), typeof(CheckGroupControl));
public bool IsExpanded
{
get { return (bool)GetValue(IsExpandedProperty); }
set { SetValue(IsExpandedProperty, value); }
}
}
}
MainWindow.xaml
<Window x:Class="VerticalWrapPanel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:VerticalWrapPanel"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Window.Resources>
<DataTemplate x:Key="CheckGroupsTemplate">
<controls:CheckGroupControl />
</DataTemplate>
</Window.Resources>
<ScrollViewer CanContentScroll="False">
<ItemsControl ItemsSource="{Binding CheckGroups}" ItemTemplate="{StaticResource CheckGroupsTemplate}" />
</ScrollViewer>
</Window>
MainWindow.xaml.cs
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
namespace VerticalWrapPanel
{
public class MyModel
{
public ObservableCollection<CheckGroup> CheckGroups { get; set; }
}
public class Check
{
public string Label { get; set; }
}
public class CheckGroup
{
public List<Check> Checks { get; set; }
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
DataContext = new MyModel
{
CheckGroups = new ObservableCollection<CheckGroup>
{
new CheckGroup
{
Checks =
new List<Check>
{
new Check {Label = "Check 0001"}
,new Check {Label = "Check 0002"}
,new Check {Label = "Check 0003"}
,new Check {Label = "Check 0004"}
,new Check {Label = "Check 0005"}
,new Check {Label = "Check 0006"}
,new Check {Label = "Check 0007"}
,new Check {Label = "Check 0008"}
,new Check {Label = "Check 0009"}
,new Check {Label = "Check 0000"}
,new Check {Label = "Check 0002"}
,new Check {Label = "Check 0003"}
,new Check {Label = "Check 0004"}
,new Check {Label = "Check 0005"}
,new Check {Label = "Check 0006"}
,new Check {Label = "Check 0007"}
,new Check {Label = "Check 0008"}
,new Check {Label = "Check 0009"}
,new Check {Label = "Check 0000"}
,new Check {Label = "Check 0002"}
,new Check {Label = "Check 0003"}
,new Check {Label = "Check 0004"}
,new Check {Label = "Check 0005"}
,new Check {Label = "Check 0006"}
,new Check {Label = "Check 0007"}
,new Check {Label = "Check 0008"}
,new Check {Label = "Check 0009"}
,new Check {Label = "Check 0000"}
}
}
, new CheckGroup
{
Checks =
new List<Check>
{
new Check {Label = "Check 0011"}
,new Check {Label = "Check 0012"}
,new Check {Label = "Check 0013"}
,new Check {Label = "Check 0014"}
,new Check {Label = "Check 0015"}
,new Check {Label = "Check 0016"}
,new Check {Label = "Check 0017"}
,new Check {Label = "Check 0018"}
,new Check {Label = "Check 0019"}
,new Check {Label = "Check 0010"}
}
}
}
};
}
}
}
I'm working on a WPF project build a couple of years ago.
One control is an expander control which groups a list of check-controls.
This list of check-controls is arranged from Left to Right, Top to Bottom by a WrapPanel!
Now my goal is to arrange the check-controls from Top to Bottom, Left to Right where the vertical wrap occurs at the bottom of the parent window! Any tips/directions in how to achieve this would be awsome!!
I have extracted the issue in a code example to highlight the issue.
Behavior of the example:
The code example has the WrapPanel's orientation set to Horizontal. This is to show you what sort of behavior I would like to achieve!
The wrap breaks at the Right side of the parent window and a new row starts. When the check-controls overflow the Bottom of the screen a vertical scrollbar appears.
Behavior I would like to achieve:
When the Bottom side of the parent window is reached (when the wrappanel is set to Vertical orientation) I want the wrap to break and start at the Top again. When the check-controls overflow the Right side of the window I want a horizontal scrollbar to appear.
Example:
In the code: change the Orientation attribute of the Wrappanel to Vertical. Notice that there is only one column overflowing all the way down, there is no wrap at the bottom of the window!
Because I'm not sure how to attach a zip file (with the demo project) I have added the code files below.
Creating a WPF application (.net framework 3.5) and copying the code in the proper locations should do.
If you do have issues running the example I can always mail you a VS2010 solution!
Project called VerticalWrapPanel
UserControl CheckControl.xaml
<UserControl x:Class="VerticalWrapPanel.CheckControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Border BorderThickness="1,1,1,1" BorderBrush="Black">
<Label Content="{Binding Label}"/>
</Border>
</UserControl>
UserControl CheckGroupControl.xaml
<UserControl x:Class="VerticalWrapPanel.CheckGroupControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:VerticalWrapPanel"
x:Name="GroupControl">
<UserControl.Resources>
<DataTemplate x:Key="CheckTemplate">
<controls:CheckControl />
</DataTemplate>
</UserControl.Resources>
<Expander BorderBrush="Black" Header="TEST" IsExpanded="{Binding ElementName=GroupControl, Path=IsExpanded}">
<ItemsControl ItemsSource="{Binding Checks}" ItemTemplate="{StaticResource CheckTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Expander>
</UserControl>
CheckGroupControl.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace VerticalWrapPanel
{
/// <summary>
/// Interaction logic for CheckGroupControl.xaml
/// </summary>
public partial class CheckGroupControl : UserControl
{
public CheckGroupControl()
{
InitializeComponent();
}
public static DependencyProperty IsExpandedProperty = DependencyProperty.Register("IsExpanded", typeof(bool), typeof(CheckGroupControl));
public bool IsExpanded
{
get { return (bool)GetValue(IsExpandedProperty); }
set { SetValue(IsExpandedProperty, value); }
}
}
}
MainWindow.xaml
<Window x:Class="VerticalWrapPanel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:VerticalWrapPanel"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Window.Resources>
<DataTemplate x:Key="CheckGroupsTemplate">
<controls:CheckGroupControl />
</DataTemplate>
</Window.Resources>
<ScrollViewer CanContentScroll="False">
<ItemsControl ItemsSource="{Binding CheckGroups}" ItemTemplate="{StaticResource CheckGroupsTemplate}" />
</ScrollViewer>
</Window>
MainWindow.xaml.cs
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
namespace VerticalWrapPanel
{
public class MyModel
{
public ObservableCollection<CheckGroup> CheckGroups { get; set; }
}
public class Check
{
public string Label { get; set; }
}
public class CheckGroup
{
public List<Check> Checks { get; set; }
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
DataContext = new MyModel
{
CheckGroups = new ObservableCollection<CheckGroup>
{
new CheckGroup
{
Checks =
new List<Check>
{
new Check {Label = "Check 0001"}
,new Check {Label = "Check 0002"}
,new Check {Label = "Check 0003"}
,new Check {Label = "Check 0004"}
,new Check {Label = "Check 0005"}
,new Check {Label = "Check 0006"}
,new Check {Label = "Check 0007"}
,new Check {Label = "Check 0008"}
,new Check {Label = "Check 0009"}
,new Check {Label = "Check 0000"}
,new Check {Label = "Check 0002"}
,new Check {Label = "Check 0003"}
,new Check {Label = "Check 0004"}
,new Check {Label = "Check 0005"}
,new Check {Label = "Check 0006"}
,new Check {Label = "Check 0007"}
,new Check {Label = "Check 0008"}
,new Check {Label = "Check 0009"}
,new Check {Label = "Check 0000"}
,new Check {Label = "Check 0002"}
,new Check {Label = "Check 0003"}
,new Check {Label = "Check 0004"}
,new Check {Label = "Check 0005"}
,new Check {Label = "Check 0006"}
,new Check {Label = "Check 0007"}
,new Check {Label = "Check 0008"}
,new Check {Label = "Check 0009"}
,new Check {Label = "Check 0000"}
}
}
, new CheckGroup
{
Checks =
new List<Check>
{
new Check {Label = "Check 0011"}
,new Check {Label = "Check 0012"}
,new Check {Label = "Check 0013"}
,new Check {Label = "Check 0014"}
,new Check {Label = "Check 0015"}
,new Check {Label = "Check 0016"}
,new Check {Label = "Check 0017"}
,new Check {Label = "Check 0018"}
,new Check {Label = "Check 0019"}
,new Check {Label = "Check 0010"}
}
}
}
};
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
尝试在项目控件上设置
VerticalScrollBarVisibility="Disabled"
和HorizontalScrollBarVisibility="Auto"
。这将禁用垂直滚动。另外,更改项目控件的模板以包含一个漂亮的滚动查看器以启用滚动。更新
您的代码仍然包含一列项目 - 这在您的情况下是正常的。我发布的 XAML 代码仅在您限制顶级项目的高度(例如使用
Height
或MaxHeight
)时才起作用。我的 XAML 代码假设您为扩展器提供的空间有限,并且您在 ItemsControl 中显示该扩展器,该控件为其项目提供了所需的空间。例如,将数据模板更改为如下所示:现在,您的扩展器将具有最大高度,当达到该高度时,它们将开始环绕。如果没有 MaxHeight,扩展器将有机会占据所需的空间,并且其内部的 WrapPanel 显然只会将所有项目布置在一根垂直线上,因为没有任何限制。
Try setting the
VerticalScrollBarVisibility="Disabled"
andHorizontalScrollBarVisibility="Auto"
on the items control. This will disable the vertical scrolling. Also, alter the template of the items control to include a nice scroll viewer to enable scrolling.UPDATE
Your code is still going with one column of items - that is normal in your case. The XAML code I posted will only work if you constraint you top-level items' height (e.g. using
Height
orMaxHeight
). My XAML code assumes that you have a limited amount of space for the expander and you are showing that expander within an ItemsControl which gives its items as much space as they want. For example, alter your data template to look as follows:Now your expanders will have a maximum height and when it is reached they will start wrapping. Without that
MaxHeight
the expander will be given the opportunity to take as much space as it wants and the WrapPanel inside it will, obviously, just lay out all the items in one vertical line since there is no constraint.要使您的
WrapPanel
垂直换行,您需要限制它的Height
例如,如果您进行
WrapPanel
定义,您将得到以这种方式换行的项目你想要的。
此外,您的
ScrollViewer
默认情况下不会显示水平滚动条。要启用它们,请设置HorizontalScrollBarVisibility
To make your
WrapPanel
wrap vertically, you need to limit it'sHeight
For example, if made your
WrapPanel
definitionyou would get the Items wrapping the way you want.
Also, your
ScrollViewer
will by default not show Horizontal scroll bars. To enable them, set theHorizontalScrollBarVisibility
感谢 Jefim 和 Rachel 将我推向正确的方向。
对我来说,缺失的链接实际上是 CheckGroup DataTemplate 上的 MaxHeight,正如 Jefim 指出的那样。
现在,我将 MaxHeight 设置为窗口的实际高度减去一些高度,以确保其他组保持可见。
我知道这可能看起来像一个肮脏的解决方案,但使用一些漂亮的 wpf 画笔,它看起来会很甜蜜,而且行为非常接近我的期望!
对代码进行更改,使其成为我想要的行为:
MainWindow.xaml
添加到 MainWindow.xaml.cs(在名称空间 VerticalWrapPanel 内)
并且 CheckGroupControl.xaml 现在有一个漂亮的水平滚动:
当然还有 CheckControl 中包装面板的方向仍然必须设置为垂直;)
Thanks Jefim and Rachel for pushing me into the right direction.
For me the missing link was actually the MaxHeight on the CheckGroup DataTemplate as Jefim pointed out.
I now set MaxHeight to the axtual height of the window minus some height to make sure the other groups stay visible.
I know this might look like a dirty solution, but with some nifty wpf brushes it will look sweet and the behavior is very close to my expectations!
Changes to the code to become the behavior I wanted:
MainWindow.xaml
Addition to MainWindow.xaml.cs (inside the namespace VerticalWrapPanel)
And the CheckGroupControl.xaml now has a nice horizontal scroll:
And of course the Orientation of the wrappanel in the CheckControl still has to be set to Vertical ;)