locked
ListBox overlapping items (change rendering order) RRS feed

  • Question

  • Hi,

    I'm trying to achieve a particular effect with a ListBox and I wondered if anyone out there could help.

    Essentially, I want a stack of layers (like squashed diamond shapes) which the user can select from. Obviously I can achieve this with a simple data template. I also want each of these layers to overlap, to give the appearance of a 3D stack of layers. However, if I set the Margin of each item to 0,0,0,-20 (which seems to be the obvious solution) each item on the list overlaps the last. I'm sure this is by design, but i'd like to reverse this behaviour somehow. Maybe rendering from the bottom to the top? I can deal with the collection that feeds it.

    Please help! 

    Thursday, May 6, 2010 8:17 AM

Answers

  • using System.Windows;
    using System.Windows.Controls;
    
    namespace WPFApp
    {
      /// <summary>
      /// Interaction logic for MainWindow.xaml
      /// </summary>
      public partial class MainWindow : Window
      {
        public MainWindow()
        {
          InitializeComponent();
        }
      }
    
      public class CascadingPanel : Panel
      {
    
    
        public double ItemOffset
        {
          get { return (double)GetValue(ItemOffsetProperty); }
          set { SetValue(ItemOffsetProperty, value); }
        }
    
        public static readonly DependencyProperty ItemOffsetProperty =
          DependencyProperty.Register("ItemOffset", typeof(double), typeof(CascadingPanel));
    
        protected override Size MeasureOverride(Size availableSize)
        {
          var desiredWidth = 0.0;
          var desiredHeight = 0.0;
          foreach (UIElement child in Children)
          {
            child.Measure(availableSize);
            desiredWidth += child.DesiredSize.Width;
            desiredHeight += child.DesiredSize.Height;
          }
          return new Size(desiredWidth, desiredHeight);
        }
        protected override Size ArrangeOverride(Size finalSize)
        {
          for (var i = 1; i <= Children.Count; i++)
          {
            var child = Children[Children.Count - i];
            child.Arrange(new Rect(ItemOffset * i, ItemOffset * i, child.DesiredSize.Width, child.DesiredSize.Height));
          }
          return finalSize;
        }
      }
    }
    

     

    <Window x:Class="WPFApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPFApp"
        Title="MainWindow" Height="350" Width="525">
      <Grid>
        <ListBox x:Name="listBox" Background="Cyan">
          <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
              <local:CascadingPanel ItemOffset="10"/>
            </ItemsPanelTemplate>
          </ListBox.ItemsPanel>
          <Rectangle Fill="Red" Height="50" Width="50"/>
          <Rectangle Fill="Blue" Height="50" Width="50"/>
          <Rectangle Fill="Green" Height="50" Width="50"/>
          <Rectangle Fill="Yellow" Height="50" Width="50"/>
        </ListBox>
      </Grid>
    </Window>
    

    Bigsby, Lisboa, Portugal
    O que for, quando for, é que será o que é...
    Wenn ist das Nunstruck git und Slotermeyer? Ja! ... Beiherhund das Oder die Flipperwaldt gersput!
    http://bigsby.eu
    Friday, May 7, 2010 10:19 AM

All replies

  • You can implement a Panel derived class of your own that calls its children Arrange() method from last to first.
    Bigsby, Lisboa, Portugal
    O que for, quando for, é que será o que é...
    Wenn ist das Nunstruck git und Slotermeyer? Ja! ... Beiherhund das Oder die Flipperwaldt gersput!
    http://bigsby.eu
    Thursday, May 6, 2010 9:15 AM
  • Are you able to provide me with an example please?
    Friday, May 7, 2010 9:53 AM
  • using System.Windows;
    using System.Windows.Controls;
    
    namespace WPFApp
    {
      /// <summary>
      /// Interaction logic for MainWindow.xaml
      /// </summary>
      public partial class MainWindow : Window
      {
        public MainWindow()
        {
          InitializeComponent();
        }
      }
    
      public class CascadingPanel : Panel
      {
    
    
        public double ItemOffset
        {
          get { return (double)GetValue(ItemOffsetProperty); }
          set { SetValue(ItemOffsetProperty, value); }
        }
    
        public static readonly DependencyProperty ItemOffsetProperty =
          DependencyProperty.Register("ItemOffset", typeof(double), typeof(CascadingPanel));
    
        protected override Size MeasureOverride(Size availableSize)
        {
          var desiredWidth = 0.0;
          var desiredHeight = 0.0;
          foreach (UIElement child in Children)
          {
            child.Measure(availableSize);
            desiredWidth += child.DesiredSize.Width;
            desiredHeight += child.DesiredSize.Height;
          }
          return new Size(desiredWidth, desiredHeight);
        }
        protected override Size ArrangeOverride(Size finalSize)
        {
          for (var i = 1; i <= Children.Count; i++)
          {
            var child = Children[Children.Count - i];
            child.Arrange(new Rect(ItemOffset * i, ItemOffset * i, child.DesiredSize.Width, child.DesiredSize.Height));
          }
          return finalSize;
        }
      }
    }
    

     

    <Window x:Class="WPFApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPFApp"
        Title="MainWindow" Height="350" Width="525">
      <Grid>
        <ListBox x:Name="listBox" Background="Cyan">
          <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
              <local:CascadingPanel ItemOffset="10"/>
            </ItemsPanelTemplate>
          </ListBox.ItemsPanel>
          <Rectangle Fill="Red" Height="50" Width="50"/>
          <Rectangle Fill="Blue" Height="50" Width="50"/>
          <Rectangle Fill="Green" Height="50" Width="50"/>
          <Rectangle Fill="Yellow" Height="50" Width="50"/>
        </ListBox>
      </Grid>
    </Window>
    

    Bigsby, Lisboa, Portugal
    O que for, quando for, é que será o que é...
    Wenn ist das Nunstruck git und Slotermeyer? Ja! ... Beiherhund das Oder die Flipperwaldt gersput!
    http://bigsby.eu
    Friday, May 7, 2010 10:19 AM
  • Amazing reply, you've really helped me understand how this works.

    Thank you so much :o)

    Friday, May 7, 2010 10:45 AM