How to access actual Height of Elements with Height=Auto - silverlight

I have a situation like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="560"/>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <!-- status infos & content start -->
<RowDefinition Height="Auto" /> <!-- status infos -->
<RowDefinition Height="Auto" /> <!-- status infos -->
<RowDefinition Height="Auto" /> <!-- status infos -->
<RowDefinition Height="*"/> <!-- content ends -->
</Grid.RowDefinitions>
<!-- image a list of custom controls directed to the first or second column on all rows here -->
<SomeCustomControl Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Grid.RowSpan="2" />
</Grid>
As you can see I have 2 Columns, the right one is more or less reserved for status information, the left for content. "SomeCustomControl" contains a control so wide it needs to be set to ColumnSpan="2". Notice there are still the status control in the right column. In SomeCustomControl I have something like this:
<Grid x:Name="LayoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
[...]
<RowDefinition Height="Auto" />
<RowDefinition Height="*" /> <!-- problem control here -->
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- a list of Controls limited to the first column -->
<ProblemControl Grid.Column="0" Grid.ColumnSpan="2" />
</Grid>
Now, the first Rows of SomeCustomControl contain controls limited to the first column, then there is a row that contains my ProblemControl. The Height of the status controls is not predetermined and depends on the shown status information. The controls in SomeCustomControl that are limited to the first column also have different heights, that are currently determined automatically through the content.
I now have the problem that ProblemControl overlaps with some of my status controls. I tried to calculate the height of my status controls and the limited controls in SomeCustomControl, but as all controls are sized dynamically I can't seem to get correct Heights. The Height of the RowDefinitions all contains Heights of type Auto and value 1, the Heights of the concrete Controls seems to be NaN.
Any ideas as to how I can calc the heights or prevent the overlapings in other ways.

I've encountered somewhat of the same problem, but came across the solution recently. The reason why you can't access the width and height properties of a control with width or height set to Auto is that the run time system is querying for the property values before they've been set. The properties ActualWidth and ActualHeight claim to get the rendered height of controls so in theory, you'd think you could simply wait until the SL application had finished loading and then perform your query, since the controls would be rendered by then and therefore, the ActualHeight/ActualWidth values should be set.
Sadly, this isn't the case either. There doesn't seem to be any guarantee when those values are set, so the workaround I used is to hook into the SizeChanged-event of the control whose values I want. SizeChanged is triggered whenever the width and height properties of a control are changed, so if I handle that event, I am guaranteed that the values are set to something other than NaN.
Do whatever logic you need to perform in a handler for that event, and you'll find the values are set.

Have you tried with ActualHeight property on control ?

You ought to be able to solve this with proper use of the Grid and some panels (DockPanel and StackPanel can be quite useful). You may also need the HorizontalAlignment or VerticalAlignment properties set to Stretch on some controls.
Your example doesn't have enough in it for us to duplicate your problem or to know that we've addressed it correctly. If you'd like more specific help, please expand the example so we can run it and see your issue.

Related

How to: datagrid cell size changed when windows size changed

Firstly, my window is set to 900px height and 600px width. It contains a datagrid with 4 columns. I've created a template for cells, the widths are, say, 100px. Now when I change the window sizes, I want cells' width to grow proportionally to size of windows. I tried to add datagrid sizes change event but it didn't work.
How can I do this? Thanks!
Update: one more question: Have any way to make the sizes of a cell is the same whether they're empty or not.
In grid definition
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="5*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*" MinWidth="70" />
<ColumnDefinition Width="Auto" />
...
MinWidth : Gets or sets the minimum width constraint of the element.

DataGrid Sizing Issue

I am trying to load data into a datagrid but I am having a nightmare with sizes. My datagrid seem to take as much space as it wants. I want it to load into the current size and display scroll bars if needed.
Could someone explain how the sizing works thank you.
Example:
<Grid Name="MainUI" Height="Auto" Width="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid Name="MainGrid" Grid.Row="1" VerticalAlignment="Top" Height="Auto" Width="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<TabControl TabStripPlacement="Bottom" Name="Main_Tab" VerticalAlignment="Top" Visibility="Visible" />
</Grid>
</Grid>
Within the tab control I create a datagrid on a new tab item in the code behind when this happens, the datagrid takes as much room as possible.
The datagrid of itemTab has no sizing on it when I load it.
Thanks
Setting the Height/Width to Auto means the control should take up as much space as it needs. This means if the control needs more space than is available in the UI, it's allowed to stretch the parent control and take up however much space it wants.
Remove the Height="Auto" and Width="Auto" to fix the issue
If it is still giving you trouble, try setting HorizontalAlignment and VerticalAlignment to Stretch. This will make the control will grow or shrink itself to take up all space available to it, however it won't expand the container it is in to take up additional space.

in wpf how do i make a datagrid fit the window height

I have a grid with 3 columns and 2 rows
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
I the lower left cell, i have a data grid, with AutoGenerateColumns=True which can load many rows. What I want to do is for the data grid height to maximize to fit the window, and for the user to be able to use the datagrid scrollbar to scroll the rows up and down.
What happens is that the datagrid flows of the bottom of the window, and even if i set the
ScrollViewer.VerticalScrollBarVisibility="Visible"
of the datagrid, the scrollbar has no effect and the rows flow downwards. Somehow the datagrid does not feel restricted...
What to do?
Try setting your DataGrid's HorizontalAlignment=Stretch and VerticalScrollBarVisibility=Auto
If that doesn't work, you may also need to bind the Grid's Height to the Window Height so that it doesn't auto-grow to fit its contents. Usually I use Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=ActualHeight}" (It might be RenderSize.ActualHeight instead of just ActualHeight... I forgot.
Another alternative is to use a DockPanel instead of a Grid since that control doesn't auto-grow to fit its contents. Instead it'll stretch its last child to fill the remaining space.
I had the same problem but binding to the Window height did not completely solve the problem for me. In my case the DataGrid still extended 2 to 3 inches below the Window's viewable area. I believe this was because my DataGrid started about 2 to 3 inches below the top of the Window.
In the end I found that it was not necessary to bind the DataGrid's height at all. All I had to do was change the DataGrid's direct container.
For me, the following XAML setup causes the DataGrid to extend beyond the size of the Window when enough rows are added. Notice that the DataGrid sits within a StackPanel.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="75"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<!-- StackPanel Content accounting for about 2-3 inches of space -->
</StackPanel>
<!-- DataGrid within a StackPanel extends past the vertical space of the Window
and does not display vertical scroll bars. Even if I bind the height to Window
height the DataGrid content still extends 2-3 inches past the viewable Window area-->
<StackPanel Grid.Row="1">
<DataGrid ItemsSource="{StaticResource ImportedTransactionList}"
Margin="10,20,10,10" MinHeight="100">
</DataGrid>
</StackPanel>
</Grid>
However, simply removing the StackPanel fixed the problem for me.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="75"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<!-- StackPanel Content accounting for about 2-3 inches of space -->
</StackPanel>
<!-- Removing the StackPanel fixes the issue-->
<DataGrid Grid.Row="1" ItemsSource="{StaticResource SomeStaticResource}"
Margin="10,20,10,10" MinHeight="100">
</DataGrid>
</Grid>
As the original post is quite old, I should note that I am using VS2017 and .Net Framework 4.6.1 but I am not sure if this has any bearing.
You have to define the column and row where the DataGrid is with *.
You say it is on the lower left cell. The row is ok but your column there has Width="Auto".
The AutoGenerateColumns=True gives a mess if Width="Auto".

Putting Canvas Inside Viewbox in Silverlight With Image

All,
I'm trying to make the silverlight app I'm making resize in a reasonable manner. To do this, I thought I would use a dynamic grid. In the center of the grid I need to put an image inside of a canvas because I will dynamically be positioning objects on top of it. Ideally, as the user makes the browser window larger, the center column would be able to resize and grow larger, thereby growing the image.
Here's what I've got:
<Viewbox Grid.Row="0" Grid.Column="1">
<Canvas x:Name="cvsCenterPane">
<Image x:Name="imgFormImage" MouseLeftButtonDown="imgFormImage_MouseLeftButtonDown"
MouseLeftButtonUp="imgFormImage_MouseLeftButtonUp" MouseMove="imgFormImage_MouseMove" />
</Canvas>
</Viewbox>
In the code behind, I then set the image source.
Here's my grid definition:
<Grid x:Name="LayoutRoot" Background="DarkCyan" ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="300" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
I think there must be some sort of unhandled exception occurring during the construction of the Viewbox because the image does not display at all. What am I doing wrong here? Am I taking the wrong approach?
There is no exception, the canvas just does not have any set dimensions which is a requirement when you want to use a ViewBox.
I for one would not use a canvas, you can stick with the grid since you can place more than one control in a cell and if you need to move the objects around you can use the Margin or a TranslateTransform in the RenderTransform property.
This does not work because you cannot set the x:Name attribute of children in a Viewbox with silverlight. At least according to a few sources:
http://blog.ningzhang.org/2008/11/viewbox-control-in-silverlight-toolkit.html
http://forums.silverlight.net/forums/p/48535/128830.aspx
http://forums.silverlight.net/forums/p/45789/123941.aspx#123941
this seems to be by design. A few workarounds have been suggested, so I will try them.
Edit: HB seems to be correct, there is no exception, the Canvas needed to have dimensions set.

WPF Layout Performance-Penalty using ColumnSpan

I have a Grid that looks something like the simplified example showed below. There are more elements in the grid but the problem is about the ListBox and the TextBlock.
If the TextBlock (or any other element with the same grid-configuration) has a ColumnSpan of two, every Update to an Item of the ListBox is very slow. I have looked with Perforator and VisualProfiler but could not see any special thing. If I set the second ColumnDefinition to a fixed width, all works as desired. The same happens, if I set the first RowHeight to a fixed height.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2">The column-span of this TextBlock seems to lead to an refresh-problem</TextBlock>
<ListBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding}"></ListBox>
</Grid>
Has someone a deeper insight into this and can explain me if this construction is a no no or what else here happens.
The problem is that the listbox creates all visual elements in the list to figure out which is the widest since your GridColumn is set to Auto in width. If your list contains many items or has a complicated (heavy) ItemTemplate, you're in trouble.
Normally, the ListBox only creates visual elements for visible elements (this is done by the VirtualizingStackPanel inside the ItemsPanelTemplate.
An alternative is to set a default width that will work 95% of the time - and then use a GridSplitter in the next column for the last 5% (So the user can widden the list). Alternate, you can use another Panel (e.g. a DockPanel) that doesn't ask the ListBox how wide it wants to be... :-)

Resources