2

I'm trying to stylize my ListBox and I would like that my Items like this:

1 4 7 10 13 16 19 22 25 28

2 5 8 11 14 17 20 23 26 29

3 6 9 12 15 18 21 24 27 30

Only 3 items vertically and the ScrollBar horizontal.

What I tried:

<Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <WrapPanel Orientation="Horizontal" /> </ItemsPanelTemplate> </Setter.Value> </Setter> 

But is not working and I have no idea what to do

2 Answers 2

1

This seems to be the solution:

public class UniformGridWithOrientation : UniformGrid { #region Orientation (Dependency Property) public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(System.Windows.Controls.Orientation), typeof(UniformGridWithOrientation), new FrameworkPropertyMetadata( System.Windows.Controls.Orientation.Vertical, FrameworkPropertyMetadataOptions.AffectsMeasure), new ValidateValueCallback(UniformGridWithOrientation.IsValidOrientation)); internal static bool IsValidOrientation(object o) { System.Windows.Controls.Orientation orientation = (System.Windows.Controls.Orientation)o; if (orientation != System.Windows.Controls.Orientation.Horizontal) { return (orientation == System.Windows.Controls.Orientation.Vertical); } return true; } public System.Windows.Controls.Orientation Orientation { get { return (System.Windows.Controls.Orientation)GetValue(OrientationProperty); } set { SetValue(OrientationProperty, value); } } #endregion protected override Size MeasureOverride(Size constraint) { this.UpdateComputedValues(); Size availableSize = new Size(constraint.Width / ((double)this._columns), constraint.Height / ((double)this._rows)); double width = 0.0; double height = 0.0; int num3 = 0; int count = base.InternalChildren.Count; while (num3 < count) { UIElement element = base.InternalChildren[num3]; element.Measure(availableSize); Size desiredSize = element.DesiredSize; if (width < desiredSize.Width) { width = desiredSize.Width; } if (height < desiredSize.Height) { height = desiredSize.Height; } num3++; } return new Size(width * this._columns, height * this._rows); } private int _columns; private int _rows; private void UpdateComputedValues() { this._columns = this.Columns; this._rows = this.Rows; if (this.FirstColumn >= this._columns) { this.FirstColumn = 0; } if (FirstColumn > 0) throw new NotImplementedException("There is no support for seting the FirstColumn (nor the FirstRow)."); if ((this._rows == 0) || (this._columns == 0)) { int num = 0; // Visible children int num2 = 0; int count = base.InternalChildren.Count; while (num2 < count) { UIElement element = base.InternalChildren[num2]; if (element.Visibility != Visibility.Collapsed) { num++; } num2++; } if (num == 0) { num = 1; } if (this._rows == 0) { if (this._columns > 0) { this._rows = ((num + this.FirstColumn) + (this._columns - 1)) / this._columns; } else { this._rows = (int)Math.Sqrt((double)num); if ((this._rows * this._rows) < num) { this._rows++; } this._columns = this._rows; } } else if (this._columns == 0) { this._columns = (num + (this._rows - 1)) / this._rows; } } } protected override Size ArrangeOverride(Size arrangeSize) { Rect finalRect = new Rect(0.0, 0.0, arrangeSize.Width / ((double)this._columns), arrangeSize.Height / ((double)this._rows)); double height = finalRect.Height; double numX = arrangeSize.Height - 1.0; finalRect.X += finalRect.Width * this.FirstColumn; foreach (UIElement element in base.InternalChildren) { element.Arrange(finalRect); if (element.Visibility != Visibility.Collapsed) { finalRect.Y += height; if (finalRect.Y >= numX) { finalRect.X += finalRect.Width; finalRect.Y = 0.0; } } } return arrangeSize; } } 

Put this class in one of your namespaces.

This is my XAML:

<Window x:Class="ListItemsVerticaly3.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ListItemsVerticaly3" Title="MainWindow" Height="350" Width="525"> <Grid> <ListView ItemsSource="{Binding numbers}"> <ListView.ItemsPanel> <ItemsPanelTemplate> <local:UniformGridWithOrientation Rows="3" /> </ItemsPanelTemplate> </ListView.ItemsPanel> </ListView> </Grid> 

And this is the result i got:

enter image description here

Forgot my code behind, simple but it does the job for this example:

public partial class MainWindow : Window { public ObservableCollection<int> numbers { get; set; } public MainWindow() { InitializeComponent(); numbers = new ObservableCollection<int>(); IEnumerable<int> generatedNumbers = Enumerable.Range(1, 20).Select(x => x); foreach (int nr in generatedNumbers) { numbers.Add(nr); } this.DataContext = this; } } 
Sign up to request clarification or add additional context in comments.

Comments

1

Try this solution:

<ListBox.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal"></StackPanel> </ItemsPanelTemplate> </ListBox.ItemsPanel> 

With ListView also we can achieve

 <ListView.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Width="{Binding (FrameworkElement.ActualWidth), RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}" ItemWidth="{Binding (ListView.View).ItemWidth, RelativeSource={RelativeSource AncestorType=ListView}}" MinWidth="{Binding ItemWidth, RelativeSource={RelativeSource Self}}" ItemHeight="{Binding (ListView.View).ItemHeight, RelativeSource={RelativeSource AncestorType=ListView}}" /> </ItemsPanelTemplate> </ListView.ItemsPanel> 

2 Comments

It's showing in just one line, like: 1 2 3 4 5 6.... I'd like to show 3 items on the first "column"
I tried with ListView in Itemspanel. if listview is not restricted you can also this itemspanel

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.