There are probably several ways to do this, here is another one. I changed the UserControl so that it automatically adjusts the size of the elements to show them as a square grid when the page resizes and / or the collection changes.
UserControl XAML Code:
<UserControl x:Class="MyControls.MyUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:MyControls" Name="myControl"> <GridView Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" ItemsSource="{Binding ElementName=myControl, Path=Items}" Width="{Binding ElementName=myControl, Path=CurrentWidth}" HorizontalAlignment="Center" Height="{Binding Width, RelativeSource={RelativeSource Self}}"> <GridView.ItemContainerStyle> <Style TargetType="GridViewItem"> <Setter Property="Margin" Value="0"/> </Style> </GridView.ItemContainerStyle> <GridView.ItemTemplate> <DataTemplate> <Border Padding="10" Width="{Binding ElementName=myControl, Path=ElementSize}" Height="{Binding ElementName=Width, RelativeSource={RelativeSource Self}}"> <Border BorderBrush="Red" BorderThickness="3"> <Image Source="ms-appx:///Assets/StoreLogo.png" Stretch="UniformToFill"/> </Border> </Border> </DataTemplate> </GridView.ItemTemplate> </GridView> </UserControl>
UserControl code behind:
public sealed partial class MyUserControl : UserControl, INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private void RaiseProperty(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); public IList Items { get { return (IList)GetValue(ItemsProperty); } set { SetValue(ItemsProperty, value); } } public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(IList), typeof(MyUserControl), new PropertyMetadata(0, (s, e) => { if (Math.Sqrt((e.NewValue as IList).Count) % 1 != 0) Debug.WriteLine("Bad Collection"); })); public void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (Math.Sqrt(Items.Count) % 1 != 0) Debug.WriteLine("Bad Collection"); RaiseProperty(nameof(ElementSize)); } private double currentWidth; public double CurrentWidth { get { return currentWidth; } set { currentWidth = value; RaiseProperty(nameof(CurrentWidth)); RaiseProperty(nameof(ElementSize)); } } public double ElementSize => (int)(currentWidth / (int)Math.Sqrt(Items.Count)) - 1; public MyUserControl() { this.InitializeComponent(); } }
MainPage XAML:
<Grid> <local:MyUserControl x:Name="myControl" Items="{Binding MyItems}"/> <Button Content="Add" Click="Button_Click"/> </Grid>
Homepage Code:
public sealed partial class MainPage : Page { private ObservableCollection<int> myItems = new ObservableCollection<int> { 1, 2, 3, 4, 5, 6, 7, 8 }; public ObservableCollection<int> MyItems { get { return myItems; } set { myItems = value; } } public MainPage() { this.InitializeComponent(); DataContext = this; MyItems.CollectionChanged += myControl.Items_CollectionChanged; } protected override Size MeasureOverride(Size availableSize) { myControl.CurrentWidth = Math.Min(availableSize.Height, availableSize.Width); return base.MeasureOverride(availableSize); } private void Button_Click(object sender, RoutedEventArgs e) => MyItems.Add(3); }
The program starts with "Bad Collection" - there are 8 elements, so you cannot make a square grid out of them, but as soon as you click on the provided button, the collection count will change to 9 and the grid should update by itself.