膨胀机内的垂直环绕面板;我无法在窗口底部包裹

时间:2011-12-13 09:23:56

标签: wpf expander wrappanel

几年前,我正在开发一个WPF项目。

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

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

现在我的目标是从上到下,从左到右排列检查控件,在父窗口的底部发生垂直换行!如何实现这一目标的任何提示/方向都会很棒!!

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

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

我希望实现的行为:  当到达父窗口的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"}
                                                                             }
                                                                 }
                                                         }

                                   };
        }
    }
}

3 个答案:

答案 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代码仅在您限制顶级项目时才有效。高度(例如使用HeightMaxHeight)。我的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" />

你会按照你想要的方式包装物品。

enter image description here

此外,默认情况下,您的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;)