Get usercontrol size in canvas

I need to add some controls for Canvas. The size of the UserControl depends on the number of items present in the ItemsControl UserControl . To correctly position the controls and draw the connecting lines between the user controls, I need the absolute width / height wrt of the parent canvas. How to get them? ActualHeight and ActualWidth return 0.

I used to ask a similar question , but could not get the right answer.

EDIT: Adding XAML od UserControl

 <UserControl x:Class="SilverlightApplication2.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}}" Loaded="UserControl_Loaded"> <Grid x:Name="LayoutRoot" Background="White"> <Border CornerRadius="3" BorderThickness="1" BorderBrush="LightGray"> <Grid Name="grid1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" > <Grid.RowDefinitions> <RowDefinition Height="40*" /> <RowDefinition Height="136*" /> </Grid.RowDefinitions> ... <Grid Name="gridPC" Grid.Row="1"> <Grid.RowDefinitions> <RowDefinition Height="55*" /> <RowDefinition Height="*" /> <RowDefinition Height="55*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> .... <ItemsControl x:Name="pitems" ItemsSource="{Binding RowsP}" Grid.Row="1"> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Width="250" Orientation="Horizontal"> <TextBlock Text="{Binding X}" Width="100" /> <TextBlock Text="{Binding Y}" Width="130" /> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> ...... </Grid> </Grid> </Border> </Grid> 

+1
source share
5 answers

You have several options that you can do this by calling Window.Measure and Window.Arrange so that all values ​​are calculated, or you can get these values ​​in the Window.Loaded event. The same problem has already been discussed on this issue .

If you determine the size of the content:

 window.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); window.Arrange(new Rect(0, 0, window.DesiredWidth, window.DesiredHeight)); 

If you are using explicit window size:

 window.Measure(new Size(Width, Height)); window.Arrange(new Rect(0, 0, window.DesiredWidth, window.DesiredHeight)); 

or

 public MyWindow() { Loaded += delegate { // access ActualWidth and ActualHeight here }; } 
+2
source

It was a long time ago, but I did something similar several years ago. I don’t remember all the details right now, I’ll look at it when I have more time this evening. I would like to give you a brief idea of ​​why you get 0 for size.

This is due primarily to the fact that the layout system in WPF takes place in two passes, measure and pass. First, the container management (in your case with the panel) asks the children for their size after this passage is completed, the container will arrange it for the children, using the dimensions that they calculated in the measure passage.

I would recommend reading this MSDN article on the "Measuring and Organizing Children" section. http://msdn.microsoft.com/en-us/library/ms745058.aspx

Let me know if this does not help, and I will spend some more time to update my memory in full detail.

Based on your editing, you can check out this post by describing how to create objects related to lines. http://denisvuyka.wordpress.com/2007/10/21/wpf-diagramming-drawing-a-connection-line-between-two-elements-with-mouse/

I think this is more aimed at your exact scenario.

+1
source

ActualWidth and ActualHeight only work after rendering the control.

To get the desired size of the control, you need to give it the opportunity to measure itself by calling it with the Measure method. After that, you can use the DesiredSize property, which will contain the desired values.

There is also a good article by Charles Petzold dealing with a similar situation:

Off-grid thinking

+1
source

I am actively creating a Silverlight control chart, and I am not taking action as the previous posters advised. I'm just waiting for the final call to onsize or other dependent OnChanged properties.

Here is what I do to load my control that has a canvas:

  • Subscribe to user control for the Loaded event ( which is the target for all dependent load event calls and size events in (step # 2) ).
  • Subscribe to the "Resized" event (which triggers events with the control loaded, as indicated in # 1).
  • All dependent properties of the OnXXXPropertyChanged event raises OnLoad (# 1).
  • As part of the loaded event, I check to see if this option is set. ActualWidth (non-zero) along with whether all my dependent properties are valid. (If all of them are not installed, as well as my global boolean flag states that it has not yet been loaded, it does nothing and exits (waiting for a subsequent call).
  • When my load event detects all dependent properties, and ActualWidth is not zero, it starts the process of using width and dependent properties to start creating my sub-controls.

NTN

+1
source

Using a Canvas-Panel instead of a Grid panel in the root element and accessing ActualWidth in the Loaded event handler should work pretty well. This article helped http://msdn.microsoft.com/en-us/library/ms745058.aspx

0
source

Source: https://habr.com/ru/post/904656/


All Articles