几年前,我正在开发一个WPF项目。
一个控件是一个扩展器控件,它将检查控件列表分组。
这个检查控件列表由WrapPanel从左到右,从上到下排列!
现在我的目标是从上到下,从左到右排列检查控件,在父窗口的底部发生垂直换行!如何实现这一目标的任何提示/方向都会很棒!!
我在代码示例中提取了该问题以突出显示该问题。
示例的行为: 代码示例将WrapPanel的方向设置为Horizontal。这是为了向您展示我想要实现的行为! 换行在父窗口的右侧中断,并开始一个新行。当检查控件溢出屏幕底部时,会出现一个垂直滚动条。
我希望实现的行为: 当到达父窗口的Bottom侧时(当wrappanel设置为Vertical orientation时)我希望换行符断开并再次从Top开始。当检查控件溢出窗口的右侧时,我想要一个水平滚动条出现。
示例: 在代码中:将Wrappanel的Orientation属性更改为Vertical。请注意,只有一列完全向下溢出,窗口底部没有换行! 因为我不确定如何附加zip文件(使用演示项目),所以我在下面添加了代码文件。 创建WPF应用程序(.net框架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"}
}
}
}
};
}
}
}
答案 0 :(得分:2)
尝试在项目控件上设置VerticalScrollBarVisibility="Disabled"
和HorizontalScrollBarVisibility="Auto"
。这将禁用垂直滚动。此外,更改项目控件的模板以包括一个漂亮的滚动查看器以启用滚动。
<Expander BorderBrush="Black" Header="TEST" IsExpanded="{Binding ElementName=GroupControl, Path=IsExpanded}">
<ItemsControl ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Auto" ItemsSource="{Binding Checks}" ItemTemplate="{StaticResource CheckTemplate}">
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer x:Name="ScrollViewer" Padding="{TemplateBinding Padding}">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Expander>
<强>更新强>
您的代码仍然使用一列项目 - 这在您的情况下是正常的。我发布的XAML代码仅在您限制顶级项目时才有效。高度(例如使用Height
或MaxHeight
)。我的XAML代码假设您有一个有限的空间用于扩展器,并且您在ItemsControl中显示该扩展器,该项扩展器为其项目提供他们想要的空间。例如,将您的数据模板更改为如下所示:
<Window.Resources>
<DataTemplate x:Key="CheckGroupsTemplate">
<controls:CheckGroupControl MaxHeight="100"/>
</DataTemplate>
</Window.Resources>
现在您的扩展器将具有最大高度,当它达到时,它们将开始包装。如果没有MaxHeight
,扩展器将有机会获得所需的空间,并且其中的WrapPanel显然只是在一条垂直线上布置所有项目,因为没有约束。
答案 1 :(得分:2)
要使WrapPanel
垂直包裹,您需要限制它Height
例如,如果您的WrapPanel
定义
<WrapPanel Orientation="Vertical" Height="100" />
你会按照你想要的方式包装物品。
此外,默认情况下,您的ScrollViewer
不会显示水平滚动条。要启用它们,请设置HorizontalScrollBarVisibility
<ScrollViewer CanContentScroll="False" HorizontalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding CheckGroups}" ItemTemplate="{StaticResource CheckGroupsTemplate}" />
</ScrollViewer>
答案 2 :(得分:0)
感谢Jefim和Rachel推动我走向正确的方向。 对我来说,缺少的链接实际上就是Jefim指出的CheckGroup DataTemplate上的MaxHeight。
我现在将MaxHeight设置为窗口的高度减去某个高度,以确保其他组保持可见。
我知道这可能看起来像一个肮脏的解决方案,但是使用一些漂亮的wpf画笔它会看起来很甜美,而且行为非常接近我的期望!
更改代码以成为我想要的行为:
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"
xmlns:converters="clr-namespace:VerticalWrapPanel"
Title="MainWindow"
Height="350"
Width="525"
Loaded="Window_Loaded"
x:Name="MyWindow">
<Window.Resources>
<converters:ActualHeightReduce x:Key="ActualHeightReduce" />
<DataTemplate x:Key="CheckGroupsTemplate">
<controls:CheckGroupControl MaxHeight="{Binding ElementName=MyWindow, Path=ActualHeight, Converter={StaticResource ActualHeightReduce}}" />
</DataTemplate>
</Window.Resources>
<ScrollViewer CanContentScroll="False">
<ItemsControl ItemsSource="{Binding CheckGroups}" ItemTemplate="{StaticResource CheckGroupsTemplate}" />
</ScrollViewer>
</Window>
添加到MainWindow.xaml.cs(名称空间VerticalWrapPanel内)
public class ActualHeightReduce : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null || string.IsNullOrEmpty(value.ToString()))
return value;
double vValue;
if (Double.TryParse(value.ToString(), out vValue))
{
return vValue - 75;
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Binding.DoNothing;
}
}
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 ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Auto" ItemsSource="{Binding Checks}" ItemTemplate="{StaticResource CheckTemplate}">
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer x:Name="ScrollViewer" Padding="{TemplateBinding Padding}">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Expander>
</UserControl>
当然,CheckControl中的wrappanel的Orientation仍然必须设置为Vertical;)