Вертикальная WrapPanel внутри расширителя;Я не могу обернуть внизу окна - PullRequest
2 голосов
/ 13 декабря 2011

Я работаю над проектом WPF, построенным пару лет назад.

Один элемент управления - это элемент расширения, который группирует список контрольных элементов управления.

Этот список контрольных элементов упорядочен слева направо, сверху вниз с помощью WrapPanel!

Теперь моя цель - расположить контрольные элементы управления сверху вниз,Слева направо, где вертикальная переноса происходит в нижней части родительского окна!Любые советы / указания в отношении того, как этого добиться, были бы потрясающими !!

Я выделил проблему в примере кода, чтобы выделить ее.

Поведение примера: В примере кода ориентация WrapPanel установлена ​​на Горизонтально.Это чтобы показать вам, какого поведения я бы хотел достичь!Обтекание разрывается в правой части родительского окна, и начинается новый ряд.Когда контрольные элементы переполняют нижнюю часть экрана, появляется вертикальная полоса прокрутки.

Поведение, которое я хотел бы достичь: Когда достигается нижняя сторона родительского окна (когда оберткаустановите вертикальную ориентацию) Я хочу, чтобы обтекание разорвалось и снова началось сверху.Когда контрольные элементы переполняют правую часть окна, я хочу, чтобы появилась горизонтальная полоса прокрутки.

Пример: В коде: измените атрибут Orientation Wrappanel на 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"}
                                                                             }
                                                                 }
                                                         }

                                   };
        }
    }
}

Ответы [ 3 ]

2 голосов
/ 14 декабря 2011

Чтобы сделать 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 голосов
/ 13 декабря 2011

Попробуйте установить 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>

UPDATE

Ваш код все еще идет с одним столбцом элементов - это нормально для вас. Размещенный мною код XAML будет работать только в том случае, если вы ограничите высоту элементов верхнего уровня (например, с помощью Height или MaxHeight). Мой код XAML предполагает, что у вас есть ограниченное пространство для расширителя, и вы показываете этот расширитель в ItemsControl, который дает его элементам столько места, сколько они хотят . Например, измените шаблон данных следующим образом:

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

Теперь ваши расширители будут иметь максимальную высоту, и когда она будет достигнута, они начнут оборачиваться. Без этого MaxHeight расширителю будет предоставлена ​​возможность занять столько места, сколько он хочет, и WrapPanel внутри него, очевидно, просто разместит все элементы в одну вертикальную линию, поскольку ограничений нет.

0 голосов
/ 14 декабря 2011

Спасибо, Джефим и Рейчел, что подтолкнули меня в правильном направлении. Для меня отсутствующей ссылкой был фактически MaxHeight на шаблоне данных CheckGroup, как указал Джефим.

Теперь я установил 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 все еще должна быть установлена ​​в вертикальное положение;)

...