Комбинация WPF между сеткой и стековой панелью - PullRequest
0 голосов
/ 18 декабря 2018

В настоящее время я пытаюсь найти / реализовать элемент управления WPF, который представляет собой комбинацию Grid и StackPanel.Это означает, что мне нравится иметь два столбца с несколькими элементами.Элемент - это другой элемент управления (например, один Label, TextBox с меткой на панели, ...).

Если элемент свернут, пустое пространство должно быть заполнено следующим элементом, что означает, что в элементе управления всегда используется как можно меньше места (без пробелов между отдельными элементами).

Я прикрепил два изображения, как это должно выглядеть.

По умолчанию: Initial

Элемент 4 свернут (обратите внимание на смещение следующих элементов): One item collapsed

У кого-нибудь есть идея или опыт, как сделать что-то подобное?

Ответы [ 4 ]

0 голосов
/ 20 декабря 2018

Я удивлен, что никто не предложил использовать UniformGrid.

Все, что вам нужно сделать, это объявить UniformGrid, установить Columns на 2 и добавить свои предметы.У свернутых элементов должно быть Visibility, установленное на Collapsed (дух).

Вот пример:

<UniformGrid Columns="2"
             VerticalAlignment="Center"
             HorizontalAlignment="Center">

    <TextBlock Text="Item 1 " />
    <TextBlock Text="Item 2 " />
    <TextBlock Text="Item 3 " />
    <TextBlock Text="Item 4 " />
</UniformGrid>

даст следующий результат:

И когда Visibility второго TextBlock установлено на Collapsed, вот как это выглядит:

0 голосов
/ 18 декабря 2018

Я бы решил эту проблему следующим образом:

  • начнем с создания сетки с двумя панелями стека (сетка находится в UserControl или любом другом заполнителе):

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <StackPanel x:Name="LeftPanel" x:FieldModifier="private" Orientation="Vertical" />
        <StackPanel x:Name="RightPanel" x:FieldModifier="private" Grid.Column="1" Orientation="Vertical" />
    </Grid>
    
  • для управления вашими предметами, создайте список предметов, желательно в коде вашего UserControl:
    private List<FrameworkElement> m_items = new List<FrameworkElement>();

  • для элементов, которые вы не хотите видеть, установите Visibility на Hidden или Collapsed.

  • , вам понадобится метод, который будет выбирать видимые элементы иразместите их поочередно на левой и правой панели.Я придумал какой-то быстрый метод, который нужно вызывать при каждом изменении списка (элемент добавляется или удаляется, видимость элемента изменяется):

    public void SortItems()
    {
        this.LeftPanel.Children.RemoveRange(0, this.LeftPanel.Children.Count);
        this.RightPanel.Children.RemoveRange(0, this.RightPanel.Children.Count);
        this.m_items.Where(i => i.Visibility == Visibility.Visible).ToList().ForEach((i) => { (this.LeftPanel.Children.Count == this.RightPanel.Children.Count ? this.LeftPanel : this.RightPanel).Children.Add(i); } );
    }
    

Метод просто удаляет все дочерние элементы панелей стека, а затем перебирает список элементов, выбирая только те из них, которые являются Visible, и добавляет один элемент на левую панель, если в обеих панелях содержится одинаковое количество элементов, и в противном случае на правую панель.,

Если вам нужен какой-то другой способ выбора, в какую панель следует добавить следующий элемент (например, ActualHeight), просто измените условие выбора панелей.

Если вы хотите сделатьЭтот метод более элегантный, вы можете добавить некоторые события или свойства зависимостей, которые будут автоматически вызывать SortItems.В любом случае, это хорошее начало.

0 голосов
/ 20 декабря 2018

Большое спасибо за все разные решения.Наконец я решил это с предложением от Синатра.Поэтому я создал свою собственную панель и переопределил ArrangeOverride:

protected override Size ArrangeOverride(Size finalSize)
    {
        List<UIElement> visibleItems = new List<UIElement>();
        double xColumn1 = 0;
        double xColumn2 = (finalSize.Width / 2) + (WIDTH_COLUMN_SEPERATOR / 2);
        double y = 0;

        double columnWidth = (finalSize.Width - WIDTH_COLUMN_SEPERATOR) / 2;

        for (int i = 0; i < InternalChildren.Count; i++)
        {
            UIElement child = InternalChildren[i];
            if (child.Visibility != Visibility.Collapsed)
            {
                visibleItems.Add(child);
            }
        }

        for (int i = 0; i < visibleItems.Count; i++)
        {
            if (i >= (visibleItems.Count - 1))
            {
                visibleItems[i].Arrange(new Rect(xColumn1, y, columnWidth, visibleItems[i].DesiredSize.Height));
            }
            else
            {
                UIElement leftItem = visibleItems[i];
                UIElement rightItem = visibleItems[i + 1];

                double rowHeight = leftItem.DesiredSize.Height > rightItem.DesiredSize.Height ? leftItem.DesiredSize.Height : rightItem.DesiredSize.Height;

                leftItem.Arrange(new Rect(xColumn1, y, columnWidth, rowHeight));
                rightItem.Arrange(new Rect(xColumn2, y, columnWidth, rowHeight));

                y += rowHeight;

                i++;
            }
        }

        return finalSize;
    }

Я также создал свой собственный UserControl для элементов:

<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Label x:Name="captionLabel" Grid.Row="0" Content="{Binding Caption}"/>
    <ContentPresenter x:Name="inputMask" Grid.Row="1" Content="{Binding InputMask, ElementName=userControlBRAIN2AttributePanelItem}" />
</Grid>

Так я получаю следующий результат (из моего тестового приложения):

введите описание изображения здесь

со свернутой позицией 3:

введите описание изображения здесь

0 голосов
/ 18 декабря 2018

вы можете использовать ListView, который использует StackPanel или DockPanel в качестве ItemTemplate.Это пример (упрощенный) того, что я использую для отображения наблюдаемой коллекции объектов в списке с помощью Grid и DockPannel:

                   <ListView x:Name="lbxDroppedDatas" SelectionMode="Single" AllowDrop="True" BorderThickness="0" Padding="0" Margin="0" ScrollViewer.HorizontalScrollBarVisibility="Disabled" SelectionChanged="lbxDroppedDatas_SelectionChanged" PreviewKeyDown="lbxDroppedDatas_PreviewKeyDown" PreviewMouseRightButtonDown="lbxDroppedDatas_PreviewMouseRightButtonDown" >
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <DockPanel Grid.Row="0" Width="{Binding Path=ActualWidth, ElementName=Container}" Height="40" Margin="1" LastChildFill="True">
                                        <CheckBox DockPanel.Dock="Left" IsChecked="{Binding IsChecked}" VerticalAlignment="Center" Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked" />
                                        <Label Content="{Binding Name}" Foreground="{Binding LineBrush}" FontWeight="Bold" FontSize="12" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="0" MouseEnter="Label_MouseEnter" MouseLeave="Label_MouseLeave"/>
                                        <TextBox DockPanel.Dock="Right" Width="60" MaxLength="14" Text="{Binding CurrentValue, StringFormat=N}" Margin="0,0,33,0" Background="Transparent" Foreground="{Binding LineBrush}" BorderBrush="{Binding LineBrush}" BorderThickness="1" VerticalAlignment="Center" HorizontalAlignment="Right" IsEnabled="False"/>
                                    </DockPanel>
                             </DataTemplate>
                        </ListView.ItemTemplate>
                        <ListView.ItemsPanel>
                            <ItemsPanelTemplate>
                                <WrapPanel Orientation="Vertical" VerticalAlignment="Stretch" Margin="0"/>
                            </ItemsPanelTemplate>
                        </ListView.ItemsPanel>
                    </ListView>

Вы можете связать видимость вашего элемента списка со свернутым или видимым свойством.

...