2010-10-20 3 views
2

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

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 кистевой панели никогда не вызывается, и даже если она будет называться, рука бы получить желаемый размер устраивать всех детей без наложения.

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

Jurica

ответ

2

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

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

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

+0

спасибо. Это тот ответ, который я искал. Очень аккуратный. Я считаю, что привязка не была необходимой, потому что она работает без нее. –

+0

Добро пожаловать. Рад, что я смог помочь. –

Смежные вопросы