Сетка со столбцами SharedSizeGroup ведет себя очень странно (* НЕ * бесконечный цикл) - PullRequest
7 голосов
/ 14 января 2012

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

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

Примечание. Неоднозначность размеров отсутствуеткак и в других вопросах, где сетка бесконечно обновляет размеры.

Я что-то делаю не так - и если да, то как я могу это исправить?- или я должен опубликовать эту проблему в Microsoft-Connect?

Код:

namespace DynamicGridColumnBinding
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;

    public partial class MainWindow
    {
        private static readonly CultureInfo[] cultureInfos =
            CultureInfo.GetCultures(CultureTypes.NeutralCultures).Take(15).ToArray();

        public MainWindow()
        {
            this.InitializeComponent();
        }

        public static IEnumerable<CultureInfo> AllCultures
        {
            get { return cultureInfos; }
        }

        private void GridInitialized(object sender, EventArgs e)
        {
            var grid = (Grid)sender;
            for ( int i = 0; i < cultureInfos.Length; i++ )
                grid.ColumnDefinitions.Add(new ColumnDefinition
                    {
                        Width = GridLength.Auto,
                        SharedSizeGroup = "g" + i,
                    });
        }

        private void ScrollViewerScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            if ( e.HorizontalChange != 0 )
                this.legendScroller.ScrollToHorizontalOffset(e.HorizontalOffset);
        }
    }
}

Xaml:

<FrameworkElement.Resources>
    <ItemsPanelTemplate x:Key="panelTemplate">
        <Grid Initialized="GridInitialized" />
    </ItemsPanelTemplate>

    <Style TargetType="ContentPresenter" x:Key="containerStyle">
        <Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource Self}, Path=(ItemsControl.AlternationIndex)}" />
        <Setter Property="Grid.Column" Value="{Binding RelativeSource={RelativeSource Self}, Path=(ItemsControl.AlternationIndex)}" />
    </Style>

    <Style TargetType="TextBlock" x:Key="textStyle">
        <Setter Property="Padding" Value="5" />
        <Setter Property="Background" Value="Lime" />
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="VerticalAlignment" Value="Center" />
    </Style>
</FrameworkElement.Resources>

<DockPanel Grid.IsSharedSizeScope="True" DataContext="{Binding Source={x:Static local:MainWindow.AllCultures}}">

    <ScrollViewer DockPanel.Dock="Top" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Disabled"
            x:Name="legendScroller">
        <ItemsControl ItemsSource="{Binding}" AlternationCount="{x:Static System:Int32.MaxValue}" Margin="0 0 500 0"
                ItemsPanel="{StaticResource panelTemplate}" ItemContainerStyle="{StaticResource containerStyle}">

            <ItemsControl.ItemTemplate>
                <DataTemplate DataType="{x:Type glob:CultureInfo}">
                    <GroupBox Header="{Binding Name}" HeaderStringFormat="[ {0} ]">
                        <TextBlock Style="{StaticResource textStyle}"
                                Text="{Binding Tag, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=2}}" />
                    </GroupBox>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>

    <TextBlock Foreground="Red" DockPanel.Dock="Top" Margin="0 10" FontSize="20" Text="some random arbitrary content in between" />

    <ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Auto" ScrollChanged="ScrollViewerScrollChanged">
        <ItemsControl ItemsSource="{Binding}" AlternationCount="{x:Static System:Int32.MaxValue}"
                ItemsPanel="{StaticResource panelTemplate}" ItemContainerStyle="{StaticResource containerStyle}">

            <ItemsControl.ItemTemplate>
                <DataTemplate DataType="{x:Type glob:CultureInfo}">
                    <Border Background="DodgerBlue" Padding="5" Margin="1">
                        <GroupBox Header="{Binding DisplayName}">
                            <TextBlock Style="{StaticResource textStyle}" Padding="5 100"
                                    Text="{Binding Tag, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=2}}" />
                        </GroupBox>
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>

</DockPanel>

Кстати:Если вы заставляете элементы верхнего ItemsControl давать размер (добавляя MinWidth="200" к GroupBox), тогда нижний ItemsControl будет действовать глупо.

BTW2: Начиная с прибл.8 столбцов с общим размером (в примере 15, контролируемых .Take(15)), вы видите, как появляется перестановка, и она удваивается по времени с каждым добавляемым столбцом - так что 20 столбцов почти не заканчиваются в течение минут.

Кстати: получение ни одного комментария в течение 3 месяцев очень расстраивает.

Ответы [ 2 ]

2 голосов
/ 24 апреля 2012

Как ни странно, я добавил этот вопрос три месяца назад, но не ответил. Вероятно, причина, по которой вы не получили ответа, в том, что это сложно!

Мне пока нечего сказать, за исключением того, что макет WPF выполняется в два этапа - измерение и аранжировка - и последующее изменение размера элементов может вызвать макет на других элементах и ​​т. Д. *

Для правильного определения размера столбцов WPF делает что-то вроде этого:

  • Измерение содержимого столбца 1
  • Упорядочить содержимое столбца 1
  • Измерение содержимого столбца 2
    • Подождите секунду, столбец 2 больше ожидаемого
    • Запуск меры для всего содержимого столбца 1
      • Упорядочить содержимое столбца 1
      • Измерение содержимого столбца 2

... и т. Д.

Извините за мой упрощенный взгляд. Сколько у вас столбцов (отсюда количество групп с общим размером)? Другой вопрос. Какие ОС и .NET Framework вы используете? Я слышал, что существует ограничение на количество SharedSizeGroups, которые вы можете иметь в WPF, например, в WindowsXP. Не уверен, что это исправлено в более поздних ОС.

В качестве обходного пути вы могли бы реализовать это поведение самостоятельно? То есть вы можете создать свое собственное присоединенное свойство, которое измеряет каждый элемент в сетке (все столбцы, все строки), а затем устанавливает размеры каждого столбца один раз? В отличие от столбца за столбцом.

С уважением,

1 голос
/ 21 ноября 2013

У меня была похожая проблема.Моя точная ситуация сопровождалась тем, как я ее решил.

У меня есть «сетка», в которой верхняя строка и левый столбец остаются на месте, как и остальные прокрутки содержимого (например, замороженные ячейки Excel).Размер содержимого варьируется и определяется во время выполнения.Также было трудно предсказать, каким будет размер.

Чтобы построить это, у меня есть в общей сложности 4 сетки - 1 внешняя сетка для макета и 3 сетки внутри нее - 1 для элементов верхнего ряда, 1для элементов левого столбца и 1 для фактического содержимого.Строки сетки содержимого синхронизируются со строками левого столбца через общую группу размеров, а также со столбцами содержимого и столбцами верхней строки.

Чтобы решить эту проблему, я заполнил данные для фактической сеткипервый в коде позади.Затем я вызвал Measure and Arrange на внешнем объекте сетки, чтобы вызвать рендер.Смотрите здесь, как это сделать.https://stackoverflow.com/a/4890217/2352625

При форсировании рендера у меня есть фактический размер каждой ячейки, который я затем использую для создания определений строк и столбцов для моих заголовков (вместо того, чтобы установить для них Авто размер).Это все еще не идеально - когда я отображаю большую сетку - но сдвиг незначителен (несколько пикселей) вместо того, чтобы прыгать, как было.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...