Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override MeasureOverride to find the size of ItemsControl

I am developing a UserControl that consists of a block with a heading and a list of items (as ItemsControl). The usercontrol is added dynamically to a canvas. I need to get the actual size of the control (including space taken by ItemsControl) before it gets rendered. I tried overriding MeasureOverride method of the UserControl hoping that the size would be reflected in DesiredSize property. But it is not working.

The XAML is:

<UserControl x:Class="MyTools.MyControl"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
       mc:Ignorable="d"
       DataContext="{Binding RelativeSource={RelativeSource Self}}">    
    <Grid x:Name="LayoutRoot" Background="White">
        <Border Name="MainBorder" CornerRadius="5" BorderThickness="2" BorderBrush="Black">
        <Grid  Name="grid1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" >
           <Grid.RowDefinitions>
                <RowDefinition Height="34" />
                <RowDefinition Height="*" />
           </Grid.RowDefinitions>
           <Grid Name="titleGrid" Grid.Row="0" Background="#FF727272">
              <TextBlock Name="titleText" HorizontalAlignment="Center" Text="{Binding ControlName}" VerticalAlignment="Center" FontSize="13" FontWeight="Bold" Foreground="Beige" />
            </Grid>
           <Grid Name="gridpr" Grid.Row="1" Background="#12C48F35">
           <Grid.RowDefinitions>
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Border Name="borderPr"  CornerRadius="3" Margin="10"  BorderThickness="1" BorderBrush="LightGray" Grid.Row="0">
                <Grid Name="gridPr" Background="#FFC1C1C1" MouseLeftButtonUp="gridPr_MouseLeftButtonUp">
                    <StackPanel>
                        <TextBlock  HorizontalAlignment="Center" Name="txtPr" Text="SubItems" VerticalAlignment="Center" Foreground="#FF584848" FontSize="12" />
                        <ItemsControl x:Name="pitems" ItemsSource="{Binding MyItems}" >
                            <ItemsControl.ItemTemplate>
                            <DataTemplate>
                            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="15,0,0,0">
                                <TextBlock Text="{Binding MyVal}" />
                            </StackPanel>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </StackPanel>
                </Grid>
            </Border>
        </Grid>
        </Grid>
        </Border>
    </Grid>
 </UserControl>   

I am overriding MeasureOverride of the UserControl as shown below:

 namespace MyTools
 {
   public partial class MyControl : UserControl
   {
       public MyControl()
       {
           InitializeComponent();
       }

       public string ControlName { get; set; }
       public object MyItems { get; set; }

       public class Row
       {
           public string MyVal { get; set; }
       }

       protected override Size MeasureOverride(Size availableSize)
       {
           var desiredSize = base.MeasureOverride(availableSize);
           var sideLength = Math.Min(desiredSize.Width, desiredSize.Height);

           desiredSize.Width = sideLength;
           desiredSize.Height = sideLength;

           return desiredSize;
       }
     }
   }

Client Code:

       MyControl control1 = new MyControl();          
       control1.ControlName = "Test Name";

       var test = new List<MyControl.Row>(
         new MyControl.Row[]
           {
               new MyControl.Row {MyVal = "Item1"},
               new MyControl.Row {MyVal = "Item2"},
               new MyControl.Row {MyVal = "Item3"}
           });

       control1.MyItems = test;

        control1.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
        MessageBox.Show(control1.DesiredSize.Height.ToString());
        canvas1.Children.Add(control1);

I am not getting the actual size using the DesiredSize.Height property from the client. Any idea on how to fix this?

like image 612
blitzkriegz Avatar asked Nov 26 '22 11:11

blitzkriegz


1 Answers

Is your user control defined to change in height to reflect the size of the contents? By default your user control will be a fixed size and not change in height just because the items control has more entries.

I think you need to add your user control inside a grid before then measuring the grid. This is how I measure controls and it seems to work well, even when measuring the control directly does not work as in your case...

MyControl control1 = new MyControl();

... your setup code for control1...

Dim containerGrid As New Grid
containerGrid.Children.Add(control1)
containerGrid.Measure(New Size(Double.MaxValue, Double.MaxValue))
containerGrid.Arrange(New Rect(0, 0, Double.MaxValue, Double.MaxValue))

...now check the grid.ActualWidth and grid.ActualHeight
like image 68
Phil Wright Avatar answered Dec 05 '22 18:12

Phil Wright