Add ScrollViewer to only one column inside a grid - c#

I'd like to add a scrollviewer to only 1 column in my grid, so that the left column stay fixed, while the right columns can scroll. Also, my right column is a tabpanel, i'd like to be able to scroll only the content.
This is what i currently have : but the whole page keeps scrolling.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<max:MaxListBox Margin="2" VerticalAlignment="Stretch" Width="100" x:Name="lsbYear" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Path=WorkingEntity.PayrollFormulas.Periods}"/>
<max:MaxTabControl Grid.Column="1" Margin="2">
<max:MaxTabItem FieldDescription="Enum:PayrollProvincesType.Federal">
<ScrollViewer>
<!-- content for this tab -->
</ScrollViewer>
</max:MaxTabItem>
<max:MaxTabItem FieldDescription="Enum:PayrollProvincesType.Quebec">
<ScrollViewer>
<!-- content for this other tab -->
</ScrollViewer>
</max:MaxTabItem>
</max:MaxTabControl>
</Grid>
Example :

Related

Expand the Grid with when the Expander is expanded

I have a problem designing my GUI in wpf.
How do i set the Grid ColumnDefinition Width dynamically,
I have a expander. And when the expander is clicked the grid should also expand and adjust with the size of the expander
As of now i have this GUI
enter image description here
And this is the xaml code
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="127"/>
<ColumnDefinition Width="665*"/>
</Grid.ColumnDefinitions>
<Expander Background="Gray" x:Name="expander" ExpandDirection="Right" Expanded="Expander_Expanded" >
<Expander.Header>
<TextBlock Text="Objects">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Expander.Header>
<StackPanel Margin="10,4,0,0">
<CheckBox Margin="4" Content="Option 1" />
<CheckBox Margin="4" Content="Option 2" />
<CheckBox Margin="4" Content="Option 3" />
</StackPanel>
<!-- Stuff XD -->
</Expander>
<Grid Grid.Column="1" Background="Red"/>
</Grid>
As of now the ColomnDefinition width is 127
I want it to adjust to at least 30. So the window will be filled with other stuff
like this
enter image description here
But my problem is how do i expand the grid when the expander is expanded.
And another thing. I can't get the size of the expander when expanded. It gives me NaN which i can't use to set the columndefinition width
Thank you so much. Sorry for my bad english
Use Auto in first column Width and it will define size of expander based on content.
If you would like that column "0" has some min Width just set the property MinWidth. (but in that case I will not recommend, but show below)
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="30"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
Also I will recommend use GridSplitter, then you will have splitter between two columns that allows to change width of columns by user in UI
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="30"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="DarkSalmon"/>
Also in expander you can only have one user-control, so "stuff" you said need to be inside some layout control like stack-panel,dock or another grid etc.
Let me know if it works as you expected.

How to structure a stacked form with WPF XAML?

On my Window, I've got a GroupBox. I'd like to build out a horizontally aligned form inside of that GroupBox. By horizontally aligned, I mean a form where the label and the input reside on the same grid row or x axis. Separate form labels + inputs reside on their own row.
Since a GroupBox can only have one child content, I assume I need to either use a Grid or StackPanel. I'm trying to use a StackPanel because that seems simpler and should achieve what I'm aiming for.
The issue I'm trying to figure out is how to group the input and label into one unit so they can reside horizontally next to each other, but stack vertically as a pair within the StackPanel.
It's probably best to use a Grid that way you an get the labels and inputs to line up vertically. While it's not impossible with a stack panel it's a whole lot harder. If you set the grid's RowDefinition heights to "Auto" the grid will only be as tall as it needs to be:
<GroupBox>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Label1"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Input1}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Label2"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Input2}"/>
etc.
</Grid>
</GroupBox>
You'll probably need to play around with margins and/or padding and horizontal alignments to get the layout exactly how you want it, but this should give you the control you need to achieve what you want.
you can use a stackpanel with orientation equal to vertical inside your groupbox and inside that stackpanel you can have another stackpanel with orientation equal to horizantal for your label and input just like following sample code.
<GroupBox Header="Sample GroupBox">
<StackPanel Orientation="Vertical">
<StackPanel Name="input1" Orientation="Horizontal">
<Label Content="input1"/>
<TextBox/>
</StackPanel>
<StackPanel Name="input2" Orientation="Horizontal">
<Label Content="input2"/>
<TextBox/>
</StackPanel>
<StackPanel Name="input3" Orientation="Horizontal">
<Label Content="input3"/>
<TextBox/>
</StackPanel>
</StackPanel>
</GroupBox>
One feature you might find useful is grid shared size scope. It can help you align elements in multiple different Grids, by sharing their column\row sizes, like this:
<GroupBox Header="Sample GroupBox">
<StackPanel Orientation="Vertical" Grid.IsSharedSizeScope="True">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="firstGroup" />
<ColumnDefinition Width="Auto" SharedSizeGroup="secondGroup" />
</Grid.ColumnDefinitions>
<Label Content="input11" Grid.Column="0" />
<TextBox Grid.Column="1" Width="100"/>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="firstGroup" />
<ColumnDefinition Width="Auto" SharedSizeGroup="secondGroup" />
</Grid.ColumnDefinitions>
<Label Content="input2222222" Grid.Column="0" />
<TextBox Grid.Column="1"/>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="firstGroup" />
<ColumnDefinition Width="Auto" SharedSizeGroup="secondGroup" />
</Grid.ColumnDefinitions>
<Label Content="input3333333333333" Grid.Column="0" />
<TextBox Grid.Column="1"/>
</Grid>
</StackPanel>
</GroupBox>
I don't say that it is necessary in the code above, but that is just example. Often, you want to use grid in for example ItemTemplate of ItemsControl, and you want all items to be aligned. Here shared size scope might help.

How stretch grid created from data template across entire cell in XAML?

I'm looking for a way to display a nested grid across the entire cell of a parent grid (content). The nested grid (menuContentControl) is created with a data template. The buttons in the nested grid should fill the cells. I create the nested grid and set the row / column with the following code:
ContentControl menuContentControl = new ContentControl();
menuContentControl.Content = this.menuViewModel;
menuContentControl.ContentTemplate = this.MenuDataTemplateLeft;
Grid.SetRow(menuContentControl, 1);
Grid.SetColumn(menuContentControl, 1);
this.content.Children.Add(menuContentControl);
The data template for menuContentControl:
<DataTemplate x:Name="MenuDataTemplateLeft">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Button x:Name="button_1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Content="{Binding MenuEntry1Description}" Grid.Row="0" Grid.Column="0"/>
<Button x:Name="button_2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Content="{Binding MenuEntry2Description}" Grid.Row="0" Grid.Column="1"/>
</Grid>
</DataTemplate>
Setting the horizontal and vertical aligment of the data template grid to 'stretch' does not work. Any ideas? Thank you :)

Button on title of ChildWindow (Silverlight) design issue

I'm designing Silverlight ChildWindow and I met one intersting problem. I defined a button on a window title as follows:
<ChildWindow.Title>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="This is textblock" Grid.Column="0"/>
<Button Content="Help" Name="btnHelp" Grid.Column="1" Width="100"
Margin="300,0,0,0" />
</Grid>
</ChildWindow.Title>
This window is resizable. When you try to resize the window, the "btnHelp" button is covered by the close button, and the "btnHelp" button is not aligned to the edge of the window also. I tried before to use a StackPanel, also I used margins in both variants (StackPanel and Grid) and they didn't help me properly. The variant in the code is latest:) Could you please give a hint, what can I do with that?
Thanks in an advance.
This is a result of what appears to be a strange choice in the ChildWindow's control template -- the Title content is not stretched, so you can't really right-align anything without hard-coding it. So, you could go ahead and just apply fixed widths to the Grid column widths:
<controls:ChildWindow.Title>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBlock Text="This is textblock" Grid.Column="0"/>
<Button Content="Help" Name="btnHelp" Grid.Column="1" />
</Grid>
</controls:ChildWindow.Title>
That's quick-and-dirty, but not very satisfying. An alternative would be to modify the ControlTemplate (at the link above) so that it behaves how you would expect. Find the ContentControl that displays the Title, and make it stretch to fill the available space, by adding HorizontalContentAlignment="Stretch":
<Style TargetType="controls:ChildWindow" x:Key="MyChildWindowStyle">
<!-- etc ... -->
<ContentControl Content="{TemplateBinding Title}" FontWeight="Bold"
HorizontalContentAlignment="Stretch"
HorizontalAlignment="Stretch" IsTabStop="False" Margin="6,0,6,0" VerticalAlignment="Center"/>
<!-- etc ... -->
</Style>
This allows you to use the normal layout controls like Grid, and it will render as expected:
<controls:ChildWindow Style="{StaticResource MyChildWindowStyle}"
...
<controls:ChildWindow.Title>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="This is textblock" Grid.Column="0"/>
<Button Content="Help" Name="btnHelp" Grid.Column="1" Width="100"/>
</Grid>
</controls:ChildWindow.Title>

ScrollViewer in ItemsControl - ScrollBar not shown but working

This is not your average "My ScrollViewer isn't working" question...
Assume a window with a grid. The sizes of column 0 and row 1 are set to Auto, column 1 and row 0 are set to *. (important)
In cell [0, 0] there is an ItemsControl with a Template with a StackPanel inside a ScrollViewer inside a Grid. The reason is simple: Show a scroll bar if not all items in the ItemsControl can be displayed. The visibility of the vertical scrollbar is set to Auto (important).
In Cell [1, 1] there is a Button that displays its width.
If the window is too small too display all items in the ItemsControl this will lead to the following:
The scroll bar will be there but it is not visible. It is working, because I can scroll using the mouse wheel. The reason seems to be that the grid column in which the ItemsControl is contained is not automatically extended to make space for the scrollbar.
If I change (nearly) any of the parameters, the scroll bar is displayed as expected and the second column is reduced in size. Can anyone explain this odd behavior?
Additional Info:
The following parameter changes will lead to the scrollbar becoming visible:
Changing size of column 0 to *
Changing size of column 1 to Auto
Changing size of row 1 to *
Removing the Button.
Moving the Button to [0, 1] or [1, 0]
Manually setting the width of the ItemsControl.
Setting the VerticalScrollBarVisibility of the ScrollViewer in the ItemsControl to Visible.
However, changing the button in [1, 1] to something else, e.g. another ItemsControl doesn't change the strange behavior, so it has nothing to with the button. Furthermore, changing the width of the Button to something that is smaller than the second column, also doesn't remove that behavior.
Complete sample code for reproduction:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="343" Width="253">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ItemsControl>
<ItemsControl.Template>
<ControlTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel IsItemsHost="True" />
</ScrollViewer>
</Grid>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.Items>
<Button Content="Column1" Height="500" />
</ItemsControl.Items>
</ItemsControl>
<Button Content="{Binding ActualWidth, RelativeSource={RelativeSource Self}}"
Grid.Column="1" Grid.Row="1" />
</Grid>
</Window>
Looks like it might be a known bug in WPF. This question deals with a ListBox's ScrollViewer, but I think the principal is the same.
As an alternative, you could add something behind the ScrollViewer that has it's width bound to the ScrollViewer's ActualWidth, which will force the column to draw the correct size
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollViewer x:Name="Test" Grid.Row="0" Grid.Column="0"
VerticalScrollBarVisibility="Auto">
<Button Content="Column1" Height="500" />
</ScrollViewer>
<Grid Grid.Column="0" Grid.Row="0"
Width="{Binding ElementName=Test, Path=ActualWidth}" />
<Button Content="{Binding ActualWidth, RelativeSource={RelativeSource Self}}"
Grid.Column="1" Grid.Row="1" />
</Grid>

Categories