Восстановление SplitterDistance внутри TabControl непоследовательно

Я пишу приложение WinForms, и одна из вкладок в моем TabControl имеет SplitContainer. Я сохраняю SplitterDistance в настройках пользовательского приложения, но восстановление несовместимо. Если отображается вкладка с разделителем, то работа восстановления и расстояние сплиттера остаются такими же, как я оставил. Если выбрана другая вкладка, расстояние между сплиттерами неверно.

Ответ 1

Я нашел проблему. Каждая страница табуляции не изменяется в соответствии с элементом управления вкладкой, пока она не будет выбрана. Например, если элемент управления вкладкой имеет ширину 100 пикселей в дизайнере, и вы только что установили ее на 500 пикселей во время загрузки, то установка расстояния сплиттера до 50 на скрытой вкладке будет изменена до расстояния сплиттера 250, когда вы выбираете эту вкладку.

Я работал над этим, записывая свойства SplitterDistance и Width в SplitContainer в настройках моего приложения. Затем при восстановлении я установил SplitterDistance для записиSplitterDistance * Width/registeredWidth.

Ответ 2

Есть более простое решение. Если Panel1 задана как фиксированная панель в свойстве SplitContainer.FixedPanel, все работает так, как ожидалось.

Ответ 3

Как уже упоминалось, управление с помощью SplitContainer не изменяется в соответствии с контролем табуляции, пока оно не будет выбрано. Если вы обрабатываете восстановление, установив SplitterDistance в процентах (storedDistance * fullDistance/100) в случае FixedPanel.None, вы увидите, что сплиттер перемещается через некоторое время из-за точности вычислений.

Я нашел другое решение для этой проблемы. Я подписываюсь на одно из событий, например событие Paint. Это событие происходит после изменения размера элементов управления, поэтому SplitContainer будет иметь правильное значение. После первого восстановления вы должны отказаться от подписки на это событие, чтобы восстановить его только один раз:

private void MainForm_Load(object sender, EventArgs e)
{
    splitContainerControl.Paint += new PaintEventHandler(splitContainerControl_Paint);
}

void splitContainerControl_Paint(object sender, PaintEventArgs e)
{
    splitContainerControl.Paint -= splitContainerControl_Paint;
    // Handle restoration here
}

Ответ 4

Для обработки всех случаев FixedPanel и ориентации должно работать следующее:

        var fullDistance = 
           new Func<SplitContainer, int>(
               c => c.Orientation == 
                  Orientation.Horizontal ? c.Size.Height : c.Size.Width);

        // Store as percentage if FixedPanel.None
        int distanceToStore =
           spl.FixedPanel == FixedPanel.Panel1 ? spl.SplitterDistance :
           spl.FixedPanel == FixedPanel.Panel2 ? fullDistance(spl) - spl.SplitterDistance :
           (int)(((double)spl.SplitterDistance) / ((double)fullDistance(spl))) * 100;

Затем выполните то же самое при восстановлении

        // calculate splitter distance with regard to current control size
        int distanceToRestore =
           spl.FixedPanel == FixedPanel.Panel1 ? storedDistance:
           spl.FixedPanel == FixedPanel.Panel2 ? fullDistance(spl) - storedDistance :
           storedDistance * fullDistance(spl) / 100;

Ответ 5

У меня была та же проблема. В моем конкретном случае я использовал формы, которые я преобразовал в табуляции и добавил к элементу управления вкладками. Решение, которое я нашел, состояло в том, чтобы установить расстояния сплиттера в событии Form_Shown, а не в событии загрузки.

Ответ 6

Сохраните расстояние сплиттера в процентах от высоты сплит-контейнера. Затем восстановите процентное расстояние разделителя, используя текущую высоту контейнера.

  /// <summary>
  /// Gets or sets the relative size of the top and bottom split window panes.
  /// </summary>
  [Browsable(false)]
  [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  [UserScopedSetting]
  [DefaultSettingValue(".5")]
  public double SplitterDistancePercent
  {
     get { return (double)toplevelSplitContainer.SplitterDistance / toplevelSplitContainer.Size.Height; }
     set { toplevelSplitContainer.SplitterDistance = (int)((double)toplevelSplitContainer.Size.Height * value); }
  }

Ответ 7

Я попытался поменять все, сделав панель Panel1 статической. SplitContainer.FixedPanel не помогло. Несмотря на то, что левая панель была исправлена, Panel2 все еще имела проблемы с правой стороны. Я в конечном итоге пробовал следующее...

Используя PictureBox внутри Panel2 и сделав его док-станцией для родителя (это означает, что я сделал док-станцию ​​PictureBox родительской Panel2), это, казалось, было моим спасением.

Кажется, в SplitContainer есть ошибка, и в дизайне я просто не мог заставить его держаться на правой стороне. Каждый раз, когда я помещал что-то близко к правой стороне Panel2, он бы приблизился к краю или, что еще хуже, прошел через показанную область Panel2.

Ответ 8

Восстановление расстояний сплиттеров дало мне много горя. Я обнаружил, что восстановление их из моих пользовательских настроек в форме (или пользовательском контроле). Событие загрузки дало гораздо лучшие результаты, чем использование конструктора. Попытка сделать это в конструкторе дала мне все виды странного поведения.

Ответ 9

Ответ - синхронизация времени. Вы должны установить SplitterDistance, когда окно выполняется с изменением размера. Затем вы должны указать флаг для окончательного изменения размера, а затем установить SplitterDistance. В этом случае все правильно

Ответ 10

Задайте содержащую TabPage.Width = TabControl.Width - 8 перед установкой SplitContainer.SplitDistance