The problem: An Window that has an ItemsControl with some items(let's say Rectangles). The window has MinWidth and MinHeight setted(eg. 300) I need that when I resize window if the rectangles has not enough space to be displayed to be displayed in 2 columns. And if in 2 columns still does not have enought space to show a scroll viewer.
What I've tried: 1. Create an extended ItemsControl:
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<local:MyGrid IsItemsHost="True" x:Name="PART_ItemsPanel" Initialized="OnItemsPanelInitialized" CanVerticallyScroll="True" CanHorizontallyScroll="True">
<local:MyGrid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</local:MyGrid.ColumnDefinitions>
<local:MyGrid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</local:MyGrid.RowDefinitions>
</local:MyGrid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
My ItemsControl has as ItemsPanelTemplate an Extended grid:
public class MyGrid : Grid, IScrollInfo { ....IScrollInfo implementation }
I use this grid thinking that when ItemsControl will PrepareContainerForItemOverride() I can use this to split the Items in two columns.
The ideea is "taken" from a conference....but I no not know what to do next... I have questions like: when I override Measure and Arrange for data grid I set the position of the items in DataGrid, but then it is called PrepareContainerForItemOverride()...then what? I should compute the no of rows I should make? but if then I resize again the window...PrepareContainerForItemOverride() won't be called ...
It is over me this issue...please give me a clue if some of you have one. Thank you guys!
I wanted to share the solution I took...if anyone needs it.
To avoid the implementation of IScrollInfo I changed ItemsControl with ListBox control. So it remains that I override Arrange. In Arrange I calculate my first column's items height and I arrange the Items in GridPanel. I use the dispatcher because the scrollViewer arrange is not always VALID and I am counting on it to get the visible height.
<ListBox x:Uid="allListBox" x:Name="adminListBoxControl" ItemTemplate ="{DynamicResource LinkButtonItemTemplate}" Margin="15" BorderBrush="Transparent" Background="Transparent">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<local:GridPanel>
<local:GridPanel.ColumnDefinitions>
<ColumnDefinition Width="0.45*"/>
<ColumnDefinition Width="0.45*"/>
<ColumnDefinition Width="0.1*"/>
</local:GridPanel.ColumnDefinitions>
<local:GridPanel.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</local:GridPanel.RowDefinitions>
</local:GridPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
protected override Size ArrangeOverride(Size finalSize)
{
Size arrangeSize = base.ArrangeOverride(finalSize);
lastItemInFirstColumn = -1;
double totalHeight = 0;
DispatcherPriority p = ScrollViewer.IsArrangeValid ? DispatcherPriority.Normal : DispatcherPriority.Input;
if (o != null)
o.Abort();
o = Dispatcher.BeginInvoke(p, (Action)(() =>
{
double fitHeight = ScrollViewer.ActualHeight;
foreach (UIElement child in this.InternalChildren)
{
if (totalHeight + child.DesiredSize.Height < fitHeight)
{
totalHeight += child.DesiredSize.Height;
lastItemInFirstColumn++;
}
else
{
if (lastItemInFirstColumn + 1 < InternalChildren.Count - (lastItemInFirstColumn + 1))
lastItemInFirstColumn++;
break;
}
}
//set items positions
ArrangeItemsInGrid();
}));
o.Completed += (s, e) => { o = null; };
return arrangeSize;
}