2

我正在研究几年前构建的 WPF 项目。

一个控件是扩展器控件,它对检查控件列表进行分组。

这个检查控件列表由 WrapPanel 从左到右、从上到下排列!

现在我的目标是从上到下,从左到右排列检查控件,其中垂直环绕发生在父窗口的底部!任何关于如何实现这一目标的提示/指导都非常棒!!

我在代码示例中提取了该问题以突出显示该问题。

示例的行为: 代码示例将 WrapPanel 的方向设置为水平。这是为了向您展示我想要实现什么样的行为!换行在父窗口的右侧中断,新行开始。当检查控件溢出屏幕底部时,会出现一个垂直滚动条。

我想实现的行为: 当到达父窗口的底部时(当包装面板设置为垂直方向时)我希望包装打破并再次从顶部开始。当检查控件溢出窗口的右侧时,我希望出现一个水平滚动条。

示例: 在代码中:将 Wrappanel 的 Orientation 属性更改为 Vertical。请注意,一路向下只有一列溢出,窗口底部没有换行!因为我不确定如何附加 zip 文件(带有演示项目),所以我在下面添加了代码文件。创建 WPF 应用程序(.net framework 3.5)并将代码复制到适当的位置应该可以。如果您在运行示例时遇到问题,我可以随时给您邮寄 VS2010 解决方案!

名为 VerticalWrapPanel 的项目

用户控件 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>

用户控件 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); }
        }

    }
}

主窗口.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>

主窗口.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"}
                                                                             }
                                                                 }
                                                         }

                                   };
        }
    }
}
4

3 回答 3

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 代码仅在您限制顶级项目的高度(例如使用Heightor MaxHeight)时才有效。我的 XAML 代码假定您的扩展器空间有限,并且您在 ItemsControl 中显示该扩展器,该扩展器为其项目提供尽可能多的空间。例如,将您的数据模板更改为如下所示:

<Window.Resources>
    <DataTemplate x:Key="CheckGroupsTemplate">
        <controls:CheckGroupControl MaxHeight="100"/>
    </DataTemplate>
</Window.Resources>

现在你的扩展器将有一个最大高度,当达到它时,它们将开始包装。否则,MaxHeight扩展器将有机会尽可能多地占用空间,并且其中的 WrapPanel 显然会将所有项目布置在一条垂直线上,因为没有约束。

于 2011-12-13T10:26:44.677 回答
2

为了使你的WrapPanel包装垂直,你需要限制它Height

例如,如果做了你的WrapPanel定义

<WrapPanel Orientation="Vertical" Height="100" />

你会得到你想要的方式包装的项目。

在此处输入图像描述

此外,ScrollViewer默认情况下您的意愿不会显示水平滚动条。要启用它们,请设置HorizontalScrollBarVisibility

<ScrollViewer CanContentScroll="False" HorizontalScrollBarVisibility="Auto">
    <ItemsControl ItemsSource="{Binding CheckGroups}" ItemTemplate="{StaticResource CheckGroupsTemplate}" />
</ScrollViewer>
于 2011-12-13T21:03:34.517 回答
0

感谢 Jefim 和 Rachel 将我推向正确的方向。正如 Jefim 所指出的,对我来说,缺失的链接实际上是 CheckGroup DataTemplate 上的 MaxHeight。

我现在将 MaxHeight 设置为窗口的实际高度减去某个高度,以确保其他组保持可见。

我知道这可能看起来像一个肮脏的解决方案,但是使用一些漂亮的 wpf 画笔它会看起来很甜蜜,并且行为非常接近我的预期!

更改代码以成为我想要的行为:

主窗口.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 中包裹面板的方向仍然必须设置为垂直;)

于 2011-12-13T23:40:26.660 回答