Проблема с пользовательской прокруткой в ​​пользовательской панели - PullRequest
2 голосов
/ 20 октября 2010

Я кодирую пользовательскую панель, представляющую карточную комбинацию.Это панель, которая будет складывать карты горизонтально.Если места недостаточно, каждая карта будет перекрывать часть карты слева от нее.Минимальная часть должна быть всегда видна.Я выполнил это, и это код:

using System;
using System.Windows;
using System.Windows.Controls;

namespace Hand
{
   public class Hand : Panel
   {
      //TODO Should be dependancy property
      private const double MIN_PART = 0.5;

      protected override Size MeasureOverride(Size availableSize)
      {
         Size desiredSize = new Size();
         foreach (UIElement element in this.Children)
         {
            element.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));

            desiredSize.Width += element.DesiredSize.Width;
            desiredSize.Height = Math.Max(desiredSize.Height, element.DesiredSize.Height);
         }
         return desiredSize;
      }

      protected override Size ArrangeOverride(Size finalSize)
      {
         //percentage of the visible part of the child.
         double part = 1;

         Double desiredWidth = 0;

         //TODO Check how to get desired size because without looping
         //this.DesiredSize is minimum of available size and size returned from MeasureOverride
         foreach (UIElement element in this.Children)
         {
            desiredWidth += element.DesiredSize.Width;
         }

         if (desiredWidth > this.DesiredSize.Width)
         {
            //Every, but the last child should be overlapped
            double lastChildWidth = this.Children[this.Children.Count - 1].DesiredSize.Width;
            part = (this.DesiredSize.Width - lastChildWidth) / (desiredWidth - lastChildWidth);

            part = Math.Max(part, MIN_PART);
         }

         double x = 0;

         foreach (UIElement element in this.Children)
         {
            Rect rect = new Rect(x, 0, element.DesiredSize.Width, element.DesiredSize.Height);
            element.Arrange(rect);
            finalSize.Width = x + element.DesiredSize.Width;
            x += element.DesiredSize.Width * part;
         }

         return finalSize;
      }
   }
}

Я хотел бы добавить полосу прокрутки, когда будет достигнута минимальная часть, чтобы пользователь все еще мог видеть все карточки.Я не могу этого сделать.Я пытался использовать ScrollViewer следующим образом:

<Window x:Class="TestScrollPanel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:h="clr-namespace:Hand;assembly=Hand"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ScrollViewer HorizontalScrollBarVisibility="Auto">
        <h:Hand>
            <Button Width="100">One</Button>
            <Button Width="150">Two</Button>
            <Button Width="200">Three</Button>
        </h:Hand>
        </ScrollViewer>
    </Grid>
</Window>

Но это не работает, потому что когда горизонтальная полоса прокрутки видна, панель MeasureOveride и ArrangeOverride of Hand никогда не вызывается, и даже если она будет вызвана, Hand получитжелаемый размер, чтобы расположить всех детей без наложения.

Может ли это быть сделано с помощью ScrollViewer вообще, а если нет, другие идеи будут оценены.Спасибо всем за помощь.

Юрика

1 Ответ

2 голосов
/ 21 октября 2010

Во-первых, измените логику вашей панели на противоположную: пусть MeasureOverride упакует карты как можно плотнее, а затем ArrangeOverride равномерно распределит их по всей заданной ширине.

Во-вторых, используйтеMinWidth свойство.Свяжите это с ScrollViewer.ActualWidth.

Таким образом, если карты могут быть плотно упакованы в ширину, меньшую ширины ScrollViewer, то ваш Hand будет растянут на все доступное пространство.А если они не могут, то ширина Hand будет равна тому, на что вы рассчитываете.

...