5

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?

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
blitzkriegz
  • 9,258
  • 18
  • 60
  • 71

2 Answers2

1

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
Phil Wright
  • 22,580
  • 14
  • 83
  • 137
-2

Try using ActualWidth and ActualHeight properties.

protected override Size MeasureOverride(Size availableSize)
{
   var desiredSize = new Size();
   var sideLength = Math.Min(ActualWidth, ActualHeight);

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

   return desiredSize;
}
Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
Maheep
  • 5,539
  • 3
  • 28
  • 47