Why is my wpf grid not being contained in its container? - wpf

I have a user control and within it I have two controls: 1) a search criteria control (custom user control) and 2) a Telerik RadGridView.
Apart from that I have a window that is the shell for my application and in it exists three regions. When this window opens I click a button and the user control mentioned above gets inserted into one of the regions. Now that the user control is loaded I edit my search criteria and click the button to populate my grid with around 1,000 records. The problem is that the grid's scroll bar doesn't become enabled because the grid control maximizes to fit the size of all the data which runs past the screen.
The only way this works properly is to set the Height property of the grid to an absolute value but then the grid doesn't size with the window.
I've tried everything that I can think of: When in the grid I set the row def size to 200*, I put the grid in a wrap panel, I put it in a dockpanel, set the VerticalAlignment to stretch, changed the dock panel to stack panel.
Shell:
<Window x:Class="WTS.CGCApplicationInterface.CGCApplicationShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:cal="http://www.codeplex.com/CompositeWPF"
xmlns:inf="clr-namespace:WTS.CGCApplicationInterface.Infrastructure;assembly=WTSCGCApplicationInterface.Infrastructure"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Width="750" Height="480"
Title="CGC Interface Window">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="200*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ItemsControl cal:RegionManager.RegionName="MenuRegion" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" />
<ItemsControl cal:RegionManager.RegionName="SwitchboardRegion" Grid.Column="0" Grid.Row="1" />
<ItemsControl cal:RegionManager.RegionName="MainRegion" Grid.Column="1" Grid.Row="1" />
</Grid>
User Control:
<UserControl x:Class="WTS.CGCApplicationInterfaceMVVM.Views.Oncor.OncorTimesheetCGC"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:wtsControls="clr-namespace:WTS.CGCApplicationInterface.UserControls;assembly=WTSCGCApplicationInterface.Infrastructure"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="600" Background="Red">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="200*" />
</Grid.RowDefinitions>
<wtsControls:CGCQueryUserControl Grid.Row="0"/>
<telerik:RadGridView ItemsSource="{Binding Path=Timesheets}" AutoGenerateColumns="False" Grid.Row="1"
ScrollViewer.VerticalScrollBarVisibility="Visible">
<telerik:RadGridView.Columns>
<telerik:GridViewToggleRowDetailsColumn></telerik:GridViewToggleRowDetailsColumn>
<telerik:GridViewDataColumn Header="MyField1" UniqueName="AssociatedObject.MyField1" IsVisible="False" />
<telerik:GridViewDataColumn Header="MyField2" UniqueName="AssociatedObject.MyField2" IsVisible="False" />

I wish I could get points for answering my own question. I do realize that this could be taken advantage of. That said, in my shell, I changed the ItemsControl region to a ContentControl and it works perfectly.

Related

Window Auto sizing when adding grid row via button [duplicate]

I have a dialog containing 2 TextBlocks, a Progress Bar and a cancel Button.
Here is the XAML:
<Window x:Class="WpfApplication4.MainWindow"
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"
xmlns:local="clr-namespace:WpfApplication4"
mc:Ignorable="d"
Title="MainWindow" Height="Auto" Width="200">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock x:Name="txtFirst" Grid.Row="0" Margin="5" TextWrapping="Wrap">This is a really really really really long string that wraps</TextBlock>
<TextBlock x:Name="txtSecond" Grid.Row="1" Margin="5" Text="A Shorter string" TextWrapping="Wrap" MaxWidth="200"/>
<ProgressBar x:Name="prgProgress" Grid.Row="2" Margin="5" Height="20" />
<Button x:Name="btnCancel" Grid.Row="3" Margin="5" Height="25" Width="50"/>
</Grid>
</Window>
I would like the Window not to have a fixed height but auto adjust its height based on the size of its children and no more, but can’t see a way to do this. At the moment when I don’t assign anything to the Window’s height, it seems to adopt a height that is much bigger that the content.
Not sure why, or where it gets height value from? If I set Windows Height = “Auto” I get the same thing. All the heights for the RowDefinitions are set to “Auto”, which I take to mean ‘set row height to be row child height’.
You need to use SizeToContent property, check the msdn link.
Example:
<Window 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"
…
SizeToContent="WidthAndHeight">

How to prevent Labels on bottom of window from disappearing when resizing?

Basically I have a window is that SizeToContent="WidthAndHeight" and I have a Label positioned on the bottom. When resizing the window the label disappears. Unless I make the window a lot bigger.
I have the following XAML code:
<Window x:Class="DateKeeper.View.Test"
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"
xmlns:local="clr-namespace:DateKeeper.View"
mc:Ignorable="d"
Title="Test" SizeToContent="WidthAndHeight"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label x:Name="label" Content="Label" HorizontalAlignment="Left" VerticalAlignment="Bottom" Grid.Column="0" Grid.Row="1" FontSize="36"/>
<TextBlock x:Name="textBlock" Grid.Column="1" Text="TextBlock" VerticalAlignment="Bottom" Grid.Row="1" FontSize="36"/>
</Grid>
</Window>
And here are the pictures:
Before Resizing
After resizing
SizeToWidthAndHeight sets the window's initial size. It doesn't prevent the user from resizing the window.
ResizeMode="NoResize" will prevent all resizing. If you want to set a minimum size and allow the window to be sized larger than that, you can't do that in pure XAML.
However, you can use that initial size as a minimum width and height with some simple code in a loaded handler, like so:
<Window
x:Class="DateKeeper.View.Test"
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"
xmlns:local="clr-namespace:DateKeeper.View"
mc:Ignorable="d"
Title="Test"
SizeToContent="WidthAndHeight"
Loaded="Window_Loaded"
>
Test.xaml.cs (or whatever you call the codebehind for the above Window):
private void Window_Loaded(object sender, RoutedEventArgs e)
{
MinWidth = ActualWidth;
MinHeight = ActualHeight;
}
You could also write an attached property that would do the same thing.
Update
This pure-XAML approach with Mode=OneTime seems promising:
<Window
...
SizeToContent="WidthAndHeight"
MinHeight="{Binding ActualHeight, RelativeSource={RelativeSource Self}, Mode=OneTime, PresentationTraceSources.TraceLevel=High}"
MinWidth="{Binding ActualWidth, RelativeSource={RelativeSource Self}, Mode=OneTime}"
...
...but in trace output, we see that it gets the values of ActualHeight and ActualWidth very early on, before the window is sized to its content, perhaps before then actual UI window object is even created -- at a point when the actual width and height are both reported as zero.
You have 50% now
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Label x:Name="label" Content="Label" FontSize="36"
Grid.Row="1" Grid.Column="0" VerticalAlignment="Bottom" HorizontalAlignment="Left" />
<TextBlock x:Name="textBlock" Text="TextBlock" FontSize="36"
Grid.Row="1" Grid.Column="1" VerticalAlignment="Bottom"/>
</Grid>
Not sure what you are trying to create, but three things:
The elements are losing visibility because they are going off of the screen because they are running out of room
Your layout puts both text elements in the second row of the Grid
a. The elements will only have 50% of the available height to render
b. FontSize and Margins/Padding will further offset this
You have two different text element types (Label and TextBlock)
a. Both have different Margin/Padding values
b. The different layout values will result in different levels of visibility
If you don't want the elements to lose visibility, you need to set a minimum size of the Window (e.g. 325x150).

Exclude control from scrolling

I have a situation in which ScrollViewer is set in the base class (Window) and my user control is dynamicaly added as a content of the window. Now, I want one of the controls (ToolBar) in my user control to be excluded from scrolling (to stay visible on top). I know there is a property HandlesScrolling on the Control class but it is internal. I have no way to put the toolbar outside the ScrollViewer because I don't have access to it.
Is there any way to do this?
The only way I can think to do that is to make your control size itself to the outer ScrollViewer and then have its own inner ScrollViewer to handle scrolling. There's some example code below but the key is binding the Height of your control to the ActualHeight of the outer ScrollerViewer like this: Height="{Binding Path=ActualHeight, RelativeSource={RelativeSource AncestorType={x:Type ScrollViewer}}}"
Outer Scrollviewer:
<ScrollViewer>
<ListBox:HandlesItsOwnScrolling />
</ScrollViewer>
Your Control:
<UserControl x:Class="ListBox.HandlesItsOwnScrolling"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Height="{Binding Path=ActualHeight, RelativeSource={RelativeSource AncestorType={x:Type ScrollViewer}}}" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0">Toolbar</Button>
<ScrollViewer Grid.Row="1">
<Border Background="AliceBlue" Height="1000" />
</ScrollViewer>
</Grid>
</UserControl>

ItemsControl-wrapping the contents inside the window

I am using an ItemsControl inside a window in WPF. The itemscontrol is bound with a collection and the collection is a group of view models(user controls). My problem - the view is going beyond the current window as a result of many view models in the collection. I tried many things to handle it with a scroll bar but no use. Any suggestions? The question really is how to contain the itemscontrol within a window(with scrolling)?
The XAML below
<Window x:Class="WpfApplicationTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:app="clr-namespace:WpfApplicationTest"
Title="MainWindow" Height="350" Width="525">
<Grid Height="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ItemsControl Grid.Row="0" Grid.Column="0" ItemsSource="{Binding UserControlCollection}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Bottom">
<Button Content="OK" Width="100" Margin="3" />
<Button Content="Cancel" Width="100" Margin="3" />
</StackPanel>
</Grid>
Wrap your ItemsControl in a ScrollViewer
Update: in your example, also set row height to * if it won't scale correctly.
In addition to #Bas's answer, set your MaxHeight and MinHeight properties to your window dimensions. You can either use the hard-coded numbers you have in the example, or create a binding to Window.ActualHeight/ActualWidth.

Why is there no vertical scroll bar for this listbox

Given the following XMAL why is no vertical scrollbar for the ListBox which is bound to an ObservableCollection of 100 strings. If I change the height of the second row from * to something fixed like 500 then a scrollbar appears, but obviously i want the row height to be what ever is available (which is what I understand * to mean)
<UserControl x:Class="SimpleStack.MainPage"
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"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<DataTemplate x:Key="ListBoxItemTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Place holder"/><TextBlock Text="{Binding}"/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="Azure">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="The Text" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"/>
<ListBox ItemsSource="{Binding ListOfNumbers}" Grid.Row="1" Grid.Column="0"
ItemTemplate="{StaticResource ListBoxItemTemplate}"/>
<TextBlock Text="Place Holder" Grid.Row="1" Grid.Column="1"/>
</Grid>
</UserControl>
The * row height is in fact "everything else available" (if you have multiple *s, it would divy that up). I am guessing that your actual issue is that "whatever is available" is infinite. Most likely the usercontrol is being given an unlimited amount of space, so it is expanding to take up as much room as it needs. Make sure you're limiting your usercontrol to the actual visible space and your listbox should get its scrollbar.
My understanding is that because of the measure/arrange layout system you are essentially telling the ListBox it can have all the vertical space it needs without being constrained. The internal ScrollViewer in the default ListBox template is therefore never constrained to trigger the scroll bar to appear.
I can see two ways to fix this for your situation:
-Specify ScrollViewer.VerticalScrollBarVisibility="Visible" on the ListBox to force the internal ScrollViewer to always show the scroll bar.
-Use an actual ScrollViewer to contain the ListBox and let that provide the scrolling capability instead of the one in the internal ListBox (you might have to tweak padding and borders to get it to look right):
<ScrollViewer Grid.Row="1" Grid.Column="0">
<ListBox ItemsSource="{Binding ListOfNumbers}"
ItemTemplate="{StaticResource ListBoxItemTemplate}"/>
</ScrollViewer>
I would prefer the second way because it would only show the vertical scroll bar if it was really necessary.

Resources