wpf is it possible to have a resizable horizontal expander? - c#

I'm new to WPF. I was able to found out how to do a resizable vertical expander from here: Combine expander and grid (resizable expander)
So I thought making a horizontal would be easy, I have tried different ways with no success.
Can it be done without complex code? To have a glidsplitter between 2 grid rows which one of them has an expander
The layout looks like this:
Left expander/gridsplitter works fine. But the expander/gridsplitter at the bottom does not. It works fine without a gridsplitter though.
My XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="10" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<Expander ExpandDirection="Left" Header="">
<Expander.Content>
<Grid>
<!-- this works -->
</Grid>
</Expander.Content>
</Expander>
<TextBox AcceptsReturn="True" />
</DockPanel>
<GridSplitter Grid.Row="1" Height="10" HorizontalAlignment="Stretch" ResizeBehavior="PreviousAndCurrent" ResizeDirection="Rows"/>
<DockPanel Grid.Row="2">
<Expander ExpandDirection="Down" Header="Summary">
<Expander.Content>
<TextBox AcceptsReturn="True" />
</Expander.Content>
</Expander>
</DockPanel>
</Grid>
If you remove the middle row and the gridsplitter, it works fine but it's not resizable.
Any help is appreciated.

The 3rd rows height should also be proportional. Specify MinHeight for the first and bottom rows so that they don't completely shrink.
Edited XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="6*" MinHeight="100"/>
<RowDefinition Height="10" />
<RowDefinition Height="*" MinHeight="50"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<Expander ExpandDirection="Left" Header="">
<Expander.Content>
<Grid>
<!-- this works -->
</Grid>
</Expander.Content>
</Expander>
<TextBox AcceptsReturn="True" />
</DockPanel>
<GridSplitter Grid.Row="1" Height="2" HorizontalAlignment="Stretch"/>
<DockPanel Grid.Row="2">
<Expander ExpandDirection="Down" Header="Summary">
<Expander.Content>
<TextBox AcceptsReturn="True" />
</Expander.Content>
</Expander>
</DockPanel>
</Grid>

The following works for me. The GridSplitter is shown when expanded and hidden when collapsed.
I use ellipses that fill the panes in the example, because that makes it easy to see how much space is taken by each panel.
Xaml
<Grid Background="Green">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" Name="expanderRow"/>
</Grid.RowDefinitions>
<Ellipse Grid.Row="0" Fill="Black"></Ellipse>
<Expander Grid.Row="2" ExpandDirection="Up" IsExpanded="False" Background="Yellow"
Expanded="Expander_Expanded"
Collapsed="Expander_Collapsed">
<Ellipse Fill="Red"/>
</Expander>
<GridSplitter Grid.Row="1" Height="15" HorizontalAlignment="Stretch" Name="expander" Visibility="Collapsed"></GridSplitter>
</Grid>
Code behind
private GridLength expandedHeight = new GridLength(0.5, GridUnitType.Star);
public MainWindow()
{
InitializeComponent();
}
private void Expander_Expanded(object sender, RoutedEventArgs e)
{
expanderRow.Height = expandedHeight;
expander.Visibility = Visibility.Visible;
}
private void Expander_Collapsed(object sender, RoutedEventArgs e)
{
expandedHeight = expanderRow.Height;
expanderRow.Height = GridLength.Auto;
expander.Visibility = Visibility.Collapsed;
}

Related

change scrollbar inside scrollviewer

there is a grid inside scrollviewer which is having a vertical scrollbar. But that scroll bar is not clear, there are 2 small horizontal lines at the bottom of scrollbar.
<ScrollViewer VerticalScrollBarVisibility="Auto" >
<Grid VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Name="DetailsBackButton" Style="{StaticResource BackButtonStyle}" Click="AttachementDetailsBackButton_Click" Grid.Row="0" Visibility="Collapsed" />
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ListBox x:Name="DetailsListbox" BorderBrush="#d2d4d5" BorderThickness="1" FontFamily="Arial" FontSize="12px" ItemsSource="{Binding}" Grid.Row="0" Visibility="Collapsed" Width="{Binding RelativeSource={RelativeSource TemplatedParent},Path=ActualHeight}" Style="{DynamicResource ListBoxDefaultStyle}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid >
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Title}" Grid.Row="0" Style="{DynamicResource AttachmentTitleText}" MouseLeftButtonDown="AttachmentTitle_MouseLeftButtonDown" >
</TextBlock>
<Border Style="{DynamicResource AreaButtonBorder}" Grid.Row="1"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
<WebBrowser Name="WebBrowser" Style="{DynamicResource WebBrowserStyle}" Visibility="Visible" Grid.Row="1" Navigating="FullTextWebBrowser_Navigating" LoadCompleted="WebBrowser_LoadCompleted" />
</Grid>
</Grid>
</ScrollViewer>
And further, if I am scrolling it a bit, these 2 horizontal lines will go off. how this can be solved? or Is there any way to move the scroll bar little down by default inside scrollviewer?
Thanks.

WPF. MVVM. Add child to grid contained in dataTemplate

I want to use a dataTemplate to show a video source from four different cameras. My datatemplate is something like this:
<DataTemplate x:Key="MultiViewTemplate">
<Grid x:Name="MultiViewGrid" ShowGridLines="True" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid x:Name="GridVideo1" Grid.Column="0" Grid.Row="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Image x:Name="imageMultiVideoStreaming1" Margin="1" Source="/app;component/Images/No_image_available.png" />
</Grid>
<Grid x:Name="GridVideo2" Grid.Column="1" Grid.Row="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Image x:Name="imageMultiVideoStreaming2" Margin="1" Source="/app;component/Images/No_image_available.png" />
</Grid>
<Grid x:Name="GridVideo3" Grid.Column="0" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Image x:Name="imageMultiVideoStreaming3" Margin="1" Source="/app;component/Images/No_image_available.png" />
</Grid>
<Grid x:Name="GridVideo4" Grid.Column="1" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Image x:Name="imageMultiVideoStreaming4" Margin="1" Source="/app;component/Images/No_image_available.png" />
</Grid>
</Grid>
</DataTemplate>
...
<Grid x:name"MainGrid" >
<ContentControl x:Name="CameraContainer" Content="{Binding}" ContentTemplate=Value="{StaticResource MultiViewTemplate}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
</Grid>
At the beginning, when I run the application, every grid should show the image No_image_avaiable.png. It works correcty. After that, I try to connect with the cameras and each video source should be shown in GridVideo1, GridVideo2...
If I do this in code-behind I can see the video from camera 1...
MainGrid.Children.Add(VideoStreamingGrid1)
but I would like to do something like this:
...GridVideo1.Children.Add(VideoStreamingGrid1)
...GridVideo2.Children.Add(VideoStreamingGrid2)
...GridVideo3.Children.Add(VideoStreamingGrid3)
...GridVideo4.Children.Add(VideoStreamingGrid4)
How can I do that?
Thanks.

Content of ScrollViewer won't extend

I have the following Window
Now if I try to pull down the Gridsplitter I can only as far as the blue Grid fits in the visible Window. But when sliding down the splitter I want a scrollbar to appear and be able to pull it down to the botton until the blue Grid is not visible any more.
<Window.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<Menu Name="MainMenu" Grid.Row="0">
</Menu>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<DockPanel x:Name="Green" Grid.Column="0" Width="Auto" Height="Auto">
<views:MyView></views:MyView>
</DockPanel>
<GridSplitter Grid.Column="0" Width="6"></GridSplitter>
<Grid Grid.Column="1" >
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Grid VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="7" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<views:ListView x:Name="Yellow" ></views:ListView>
</Grid>
<GridSplitter Grid.Row="1" Height="7" HorizontalAlignment="Stretch" />
<Grid Grid.Row="2" >
<ContentControl Content="{Binding LoadedControl}" x:Name="Blue" />
</Grid>
</Grid>
</ScrollViewer>
</Grid>
</Grid>
<StatusBar x:Name="StatusBar" Grid.Row="2">
</StatusBar>
</Grid>
</Window.Content>
What do I have to change here?
Move your ScrollViewer further down so it wraps the blue ContentControl in row 2, and ensure the ContentControl has a Height or MinHeight set.
ScrollViewers allow their child to take up as much space as they want, and only shows scrollbars if the child object gets larger than the ScrollViewer size.
Also as a side note, you can remove some of those extra Grid's in your layout to make it easier to read. Here's an example with a bunch of them removed, and the first one being replaced with a DockPanel :)
<DockPanel>
<Menu Name="MainMenu" DockPanel.Dock="Top" Height="25" />
<StatusBar x:Name="StatusBar" DockPanel.Dock="Bottom" Height="25"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="6" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<views:MyView x:Name="Green" Grid.Column="0" />
<GridSplitter Grid.Column="1" Width="6" />
<Grid Grid.Column="2" >
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="7" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<views:ListView x:Name="Yellow" Grid.Row="0" />
<GridSplitter Grid.Row="1" Height="7" HorizontalAlignment="Stretch" />
<ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto">
<ContentControl x:Name="Blue" MinHeight="400"/>
</ScrollViewer>
</Grid>
</Grid>
</DockPanel>
Hope you find a better solution XD as mine use a code behind
I used the DragDelta event of the control GridSplitter and enlarge the height of the grid so the ScrollBar can be activated
The xaml Code:
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<DockPanel x:Name="Green" Grid.Column="0" Width="Auto" Height="Auto" Background="#FF0CFA8F" >
<local:BusyUserControl Width="200" Height="200"/>
</DockPanel>
<GridSplitter ResizeDirection="Rows" Grid.Column="0" Width="6"></GridSplitter>
<ScrollViewer x:Name="MainScrollViewer" VerticalScrollBarVisibility="Auto" Grid.Column="1" >
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="7" />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid >
<views:ListView x:Name="Yellow" ></views:ListView>
</Grid>
<GridSplitter Grid.Row="1" Height="7" ResizeBehavior="PreviousAndNext" HorizontalAlignment="Stretch" DragDelta="GridSplitter_DragDelta" />
<Grid Grid.Row="2">
<ContentControl Content="{Binding LoadedControl}" x:Name="Blue" />
</Grid>
</Grid>
</ScrollViewer>
</Grid>
The code Behind:
private void GridSplitter_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (e.VerticalChange > 1500 || e.VerticalChange > -15000) return;
if (e.VerticalChange > 0 || Visibility.Visible.Equals(MainScrollViewer.ComputedVerticalScrollBarVisibility))
{
this.MainGrid.Height = this.MainGrid.ActualHeight + e.VerticalChange;
}
e.Handled = true;
}
Note:
When the scrollbar is no more visible I stop shrinking the grid (keep the grid stretshed) that’s the meaning of the condition
Visibility.Visible.Equals(MainScrollViewer.ComputedVerticalScrollBarVisibility)
Hope this could help you and thx for the question :)
if you want to display a vertical scroll bar for each part in the splitted grid try the following code :
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<DockPanel x:Name="Green" Grid.Column="0" Width="Auto" Height="Auto" Background="#FF0CFA8F" >
<local:BusyUserControl Width="200" Height="200"/>
</DockPanel>
<GridSplitter Grid.Column="0" Width="6"></GridSplitter>
<Grid Grid.Column="1" >
<Grid VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="7" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="0" >
<Grid >
<views:ListView x:Name="Yellow" ></views:ListView>
</Grid>
</ScrollViewer>
<GridSplitter Grid.Row="1" Height="7" HorizontalAlignment="Stretch" />
<ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="2" >
<Grid Grid.Row="2" >
<ContentControl Content="{Binding LoadedControl}" x:Name="Blue" />
</Grid>
</ScrollViewer>
</Grid>
</Grid>
</Grid>
otherwise clarify your need

Hide and auto resize columns with GridSplitter

I've a project with 1 header row and 1 content row. The content row is divided into 3 columns (groupboxes). These 3 columns are realized with GridSplitter.
Source Code:
<Window
x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewMenu="clr-namespace:Cons.ViewMenu"
Title="Test Gridsplitter"
Height="700"
Width="1000">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisConverter" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Row 0 -->
<GroupBox Name="Menu" Grid.Row="0">
<ViewMenu:LockedToolBar>
<ToggleButton x:Name="HideColumn0Button" IsChecked="True" Width="80" Height="40">Hide C0</ToggleButton>
<ToggleButton x:Name="HideColumn1Button" IsChecked="True" Width="80" Height="40">Hide C1</ToggleButton>
<ToggleButton x:Name="HideColumn2Button" IsChecked="True" Width="80" Height="40">Hide C2</ToggleButton>
</ViewMenu:LockedToolBar>
</GroupBox>
<!-- Row 1 -->
<GroupBox Name="Body" Grid.Row="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MinWidth="80" />
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*" MinWidth="80" />
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*" MinWidth="80" />
</Grid.ColumnDefinitions>
<!-- Column 0 -->
<GroupBox Header="Column 0"
Name="ds"
Grid.Row="0"
Grid.Column="0"
Visibility="{Binding Path=IsChecked, ElementName=HideColumn0Button, Converter={StaticResource BoolToVisConverter}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ViewMenu:LockedToolBar Grid.Row="0">
</ViewMenu:LockedToolBar>
</Grid>
</GroupBox>
<!-- Column 1 -->
<GroupBox Header="Column 1"
Grid.Row="0"
Grid.Column="2"
Visibility="{Binding Path=IsChecked, ElementName=HideColumn1Button, Converter={StaticResource BoolToVisConverter}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ViewMenu:LockedToolBar Grid.Row="0">
</ViewMenu:LockedToolBar>
</Grid>
</GroupBox>
<!-- Column 2 -->
<GroupBox Header="Column 2"
Grid.Row="0"
Grid.Column="4"
Visibility="{Binding Path=IsChecked, ElementName=HideColumn2Button, Converter={StaticResource BoolToVisConverter}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ViewMenu:LockedToolBar Grid.Row="0">
</ViewMenu:LockedToolBar>
</Grid>
</GroupBox>
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="5"/>
<GridSplitter Grid.Column="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="5"/>
</Grid>
</GroupBox>
</Grid>
</Window>
I click on HideColumn1Button, column 1 is hidden, but the other two columns have the same width as before. But I want, that column 0 and 2 are auto resized to the complete width.
Does anyone of you know, how to do that?
If you wish to bind it using a checkbox then you can try the following code, just build a library out of it and make use of extended column definition. Courtesy(immortalus)
http://www.codeproject.com/Articles/437237/WPF-Grid-Column-and-Row-Hiding
Alternatively, on the button_click or checkbox_checked you can write code(I have named the grid as testgrid), remember to add the reverse code as well:
testgrid.ColumnDefinitions[0].Width = new GridLength(0);
testgrid.ColumnDefinitions[0].MinWidth = 0;
An even more extended version is to write your own Storyboard, but the above two should help.
Regards
Kajal
Your BooleanToVisibilityConverter needs to return Visibility.Collapsed, not Visibility.Hidden. That would be the visual equivalent to setting the width to 0.
Edit
Find your definition of BooleanToVisibilityConverter somewhere in your code.
You should only have 3 columns. Put the GridSplitters in Columns 1 and 2, HorizontalAlignment="Left". For each GroupBox set Margin="5,0,0,0".
Please try to verify that BooleanToVisibilityConverter needs to return Visibility.Collapsed, not Visibility.Hidden.
BooleanToVisibilityConverter.cs source code in C# .NET
You should only have 3 columns with Auto width for column 0. Put the GridSplitters in Columns 1 and 2.
Here is the code i tried :
<Window
x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewMenu="clr-namespace:Cons.ViewMenu"
Title="Test Gridsplitter"
Height="700"
Width="1000">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisConverter" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Row 0 -->
<GroupBox Name="Menu" Grid.Row="0">
<StackPanel>
<ToggleButton x:Name="HideColumn0Button" IsChecked="True" Width="80" Height="40">Hide C0</ToggleButton>
<ToggleButton x:Name="HideColumn1Button" IsChecked="True" Width="80" Height="40">Hide C1</ToggleButton>
<ToggleButton x:Name="HideColumn2Button" IsChecked="True" Width="80" Height="40">Hide C2</ToggleButton>
</StackPanel>
</GroupBox>
<!-- Row 1 -->
<GroupBox Name="Body" Grid.Row="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" MinWidth="150"/>
<ColumnDefinition Width="*" MinWidth="150"/>
</Grid.ColumnDefinitions>
<!-- Column 0 -->
<GroupBox Header="Column 0"
Name="ds"
Margin="5,0,0,0"
Grid.Row="0"
Width="150"
Grid.Column="0"
Visibility="{Binding Path=IsChecked, ElementName=HideColumn0Button, Converter={StaticResource BoolToVisConverter}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
</StackPanel>
</Grid>
</GroupBox>
<!-- Column 1 -->
<GroupBox Header="Column 1"
Grid.Row="0"
Grid.Column="1"
Margin="5,0,0,0"
Visibility="{Binding Path=IsChecked, ElementName=HideColumn1Button, Converter={StaticResource BoolToVisConverter}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
</StackPanel>
</Grid>
</GroupBox>
<!-- Column 2 -->
<GroupBox Header="Column 2"
Grid.Row="0"
Margin="5,0,0,0"
Grid.Column="2"
Visibility="{Binding Path=IsChecked, ElementName=HideColumn2Button, Converter={StaticResource BoolToVisConverter}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
</StackPanel>
</Grid>
</GroupBox>
//Put the GridSplitters in Columns 1 and 2, HorizontalAlignment="Left".
<GridSplitter Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Stretch" Width="5"/>
<GridSplitter Grid.Column="2" HorizontalAlignment="Left" VerticalAlignment="Stretch" Width="5"/>
</Grid>
</GroupBox>
</Grid>
</Window>
Before hide
After Hide
How to create a GridSplitter that occupies a column
To specify a GridSplitter that occupies a column in a Grid, set the Column attached property to one of the columns that you want to resize. If your Grid has more than one row, set the RowSpan attached property to the number of rows. Then set the HorizontalAlignment to Center, set the VerticalAlignment property to Stretch, and set the Width of the column that contains the GridSplitter to Auto.
The following example shows how to define a vertical GridSplitter that occupies a column and resizes the columns on either side of it.
Credit : http://msdn.microsoft.com/en-us/library/ms745672(v=vs.110).aspx
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto" />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
..
<GridSplitter Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Stretch"
Background="Black"
ShowsPreview="True"
Width="5"
/>

WPF Listbox grows outside screen size (MVVM light)

I have a typical MVVM structure. A mainwindow consists of some labels and a viewmodel (bound as ContentControl). This viewmodel has a listbox where I add entries. As the list grows the height of my viewmodel grows as well and thus the height of the whole application. Unfortunately the size doesn't stop at the edge of the screen and just grows out of the screen. I tried all the different size-restrictions on the mainwindow, the viewmodel is stretched in both dimensions.
Furthermore, I tried to get a scrollbar for the listbox but didn't succeed (or it's just there but not enabled if I force it.)
How can I restrict the maximal size to be the resolution of the screen (fullscreen) and get a scrollbar for the listbox when the size is reached?
€: Okay, here should be the relevant part of my code. I tried a fixed size of 1024x768 but even that doesn't work.
MainWindow.xaml
<Window x:Class="SWS.MainWindow"
DataContext="{Binding Main, Source={StaticResource Locator}}"
Width="1024"
Height="768"
MaxWidth="1024"
MaxHeight="768">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ContentControl Grid.Row="0" Content="{Binding CurrentViewModel}" />
</Grid>
</Window>
The ViewModel in question
<UserControl x:Class="SWS.Views.ProgramView"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<Label Width="65" Content="{x:Static p:Resources.PrV_Number}" />
<Label Width="75" Content="{x:Static p:Resources.PrV_Weight}" />
<Label Width="55" Content="{x:Static p:Resources.PrV_Action}" />
<Label Content=" " />
</DockPanel>
<ListBox Grid.Row="1"
VerticalAlignment="Stretch"
ItemsSource="{Binding ParticleCollection}"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel>
<TextBlock Text="{Binding ID}" Width="53" />
<TextBlock Text="{Binding Weight, StringFormat=F4}" Width="65" />
<TextBlock Text="{Binding Action}" Width="52" />
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>
You need to set the row height to * on your Window for ContentControl and your ListBox in UserControl to fill available space than try to get what it needs.
This worked fine:
MainWindow.xaml:
<Window x:Class="SWS.MainWindow"
DataContext="{Binding Main, Source={StaticResource Locator}}"
Width="1024"
Height="768"
MaxWidth="1024"
MaxHeight="768">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentControl Grid.Row="0" Content="{Binding CurrentViewModel}" />
</Grid>
</Window>
and UserControl:
<UserControl x:Class="SWS.Views.ProgramView"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
...
</Grid>
</UserControl>
Could also do this in a couple more ways:
In your Window you can just remove the <Grid.RowDefinitions>...<Grid.RowDefinitions> completely. The default behavior is what your looking for.
When you have more than 1 row you can either choose to specify Height="*" or just remove the Height Property from the RowDefinition
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>

Categories