DataGrid Sizing Issue - wpf

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.

Related

Prevent focus/tabbing into non visible element in UI

For example, I have Grid with two rows and GridSplitter between them. When one the rows is not visible in UI (eg. splitter is all the way on top; real case scenario is more complicated with nested controls) elements are still reachable via tab key - I would like to prevent that.
I am aware of IsVisible property of FrameworkElement (is true even for such elements) and/or IsEnabled/IsTabStop and KeyboardNavigation class in general, but none of them solves my problem. My elements are usable etc., just not currently visible in UI because of grid splitter. Basically only framework elements which can be reached by mouse should also participate in tab key functionality.
Simplest case when it can be reproduced is following content of main window (move splitter to upper most position).
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="10"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" KeyboardNavigation.TabNavigation="Once"/>
<GridSplitter Height="10" Grid.Row="1" KeyboardNavigation.TabNavigation="Once" HorizontalAlignment="Stretch"/>
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox x:Name="PART_Problem" Grid.Row="0" KeyboardNavigation.TabNavigation="Once"/>
<TextBox Grid.Row="1" KeyboardNavigation.TabNavigation="Once"/>
</Grid>
</Grid>
Result should be that non-visible elements should be skipped and next visible element should be focused instead. This functionality should be compatible with KeyboardNavigation.ControlTabNavigation.
Edit 1: changed sample a little in order to show, that PART_Problem keeps ActualHeight to some non-zero value, which eliminates solutions based on size changes.
Try setting the property Focusable="False" in XAML

How to customize the visible area of the scroll viewer's content

The ScrollViewer's default behavior is, that the content stops on the bottom of the ScrollViewer's view port:
I would like to change the behavior, so that the content can be scrolled to the top of the scroll ScrollViewer's view port:
a) Is it possible to configure the existing scroll viewer that way?
b) If not, what is the best way to achieve that behavior?
Embed the scrollable content in a Grid with 3 rows. The scrollable content occupies the second row. The other two have the same Height of the ScrollViewer:
<ScrollViewer Height="50">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<YourScrollableContent Grid.Row="1"/>
</Grid>
</ScrollViewer>
I've no way to test it in order to see if this code is perfect, but I'm sure this can be a way :)
Maybe you can bind the Height of the 2 rows with the Height of the ScrollViewer:
<RowDefinition Height="{Binding Path=Height,
RelativeSource={RelativeSource AncestorType=ScrollViewer}}"/>

WPF XAML ListView with ScrollBars

I have a ListView which is showing both scroll bars. To achieve that, I places my ListView within a Border located in a Grid like below:
<Window ...
MinWidth="600" MinHeight="500" Width="800" Height="500"
Topmost="True"
WindowStartupLocation="CenterScreen"
SizeToContent="Height" WindowStyle="None">
<Window.Resources>
<ResourceDictionary>
...
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" MinHeight="60"/>
<RowDefinition Height="48"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="370"/> <-- THIS IS HARDCODED TO 370 BUT I NEED IT TO BE RESIZABLE
</Grid.RowDefinitions>
<Grid Margin="5,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4"/>
<ColumnDefinition Width="346*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding MyName}" Grid.Column="1"
Style="{StaticResource MyNameStyle}" Margin="0,5,0,5" />
</Grid>
<Border BorderBrush="{StaticResource MyBrush}" Grid.Row="1" Grid.Column="0" >
<ListView
x:Name="lstMyListView"
Margin="0,0,0,0"
BorderBrush="Transparent"
ItemsSource="{Binding MyItems}"
SelectedIndex="0"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto">
...
...
</ListView>
...
...
</Border>
...
...
</Grid>
</Grid>
</Window>
This is all in a form that is resizable. Therefore, the ListView should also resize but it should do that only when user resizes the form. The problem with my hard coded value above is obvious, the ListView will not resize but stay at constant height=370.
I know I can set this to 370* but in that case, my List will resize to fit all items. I want to limit this so that resizing only occurs when user resizes the form. So, ListView should show scroll bars if there are more items and as the user resizes form, that scroll bar should go away if form is resized to height that can accommodate all items in ListView.
UPDATE:
Instead of hard coding the height to 370 above, I have tried setting the height to , Auto, and 370. All of these would expand the ListView (and therefore form, too) to accommodate all items in the ListView.
UPDATE 2:
Updated XAML to show whole tree structure.
UPDATE 3:
As per Rachel's suggestion, set hardcoded 370 to "*" in commented line above in XAML and that produces form resized so that the ListView fits all items in it. I added screenshot showing the form as it opens and a screenshot showing how it should look like when it opens. As you can see, it resizes hightwise to accomodate all itesm.
What I need is that form and ListView stay in their set size and resize only if user resizes the form.
If I understand your question correctly, you are saying the form loads as too large of a size because the ListView is growing to it's full height. If that's the case, remove the SizeToContent="Height" from the <Window> tag since it is making the window's initial height be equal to whatever height the content is, which includes the fully sized ListView.
By setting ScrollViewer.VerticalScrollBarVisibility="Visible" & MaxHeight="700"
scroll bar will be visible
MaxHeight to any value
Hi I think i have understand you. So, i am trying:
So, you want to have your ListView at least a height of 370 and then only resizes if the window resizes (increment and decrement of window size).
Setting MinHeight of 2nd RowDefinition could help
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition MinHeight="370"/> <!-- THIS IS HARDCODED....-->
</Grid.RowDefinitions>
.....
</Grid>
Thank you.

Vertical sizing in WPF trouble

I'm having trouble vertically sizing the CheckListBox control from https://wpftoolkit.codeplex.com/. I'm a week-old newbie in WPF, so this is probably a general issue with (vertical) sizing.
Given my grid, I want the first 5 rows to size whatever size, they need to be, and in my viewport, I want the CheckListBox control in row 6 to simply fill the remaining space vertically.
My problem is, that when I fill the CheckListBox with a lot of elements, the control just expands / overflows the viewport. What I want it to do, is to assume the height of the remaining space vertically, which will make it display an inner scrollbar.
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0">Some title</Label>
<RadioButton Grid.Row="1" GroupName="NameSortRadioButtonGroup">Firstname Lastname</RadioButton>
<RadioButton Grid.Row="2" GroupName="NameSortRadioButtonGroup">Lastname, Firstname</RadioButton>
<TextBox Grid.Row="3" Margin="0,5" />
<Label Grid.Row="4" Content="{Binding ElementName=MyCheckListBox, Path=SelectedItems.Count}" />
<xctk:CheckListBox
Grid.Row="5"
Name="MyCheckListBox"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
Height="Auto"
/>
</Grid>
I have left out some parent elements to simplify. The Grid is in a grid, that's in a canvas, that's in a grid, and this outer grid is direct child of the Window element.
I have tried wrapping the CheckListBox control in a StackPanel with Height="Auto" (to eliminate the possibility of a bug in the CheckListBox) and also here to set the height of the CheckListBox using
Height="{Binding ElementName=CheckListBoxStackPanelWrapper, Path=ActualHeight}"
I also initially tried to do the whole thing with first a StackPanel and later a DockPanel instead of the Grid control.
In all cases, the CheckListBox just flows out of the window/viewport. If I give it an explicit height, it behaves correctly, but I obviously want my window to be resizable.
What shall I do?
To sum up comments because your outer control is a Canvas which does not restrict its child elements From MSDN:
Child elements of a Canvas are always given the full size that they desire
which means that Grid will be given as much space as it require. One solution is to remove the Canvas part or restrict the size size of Grid or expanding row

How to access actual Height of Elements with Height=Auto

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.

Resources