WPF ScrollBar not showing up on Grid - c#

Here is my Grid, no matter what I tried I can't get the VerticalScrollBar to show up.
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden" Style="{StaticResource MaterialDesignScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
</ScrollViewer>
</Grid>
I need the Grid to be Stretched both Horizontally and Vertically so that it can dynamically resize itself.
I even tried setting the Height as Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=ActualHeight}" for both the Grid and ScrollViewer.

Don't enclose scroll viewer inside another grid.
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden" Style="{StaticResource MaterialDesignScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
</ScrollViewer>

Related

How to get the width of wpf expander togglebutton in codebehind

I want to build a customcontrol where expandable rows are added to grid. In order to match the columns of the expandable row, I added another grid as expander header and content. However, the columns are slightly tilted to the right (see picture). I think it is because of the header size?
How do I access the width of the togglebutton code, so I can change the columndefinitions accordingly?
Thanks!
There are a few ways to approach this.
One would be trying to find the width of that togglebutton yourself by looking at the control template and compensating - but this is unreliable as the template can change across .NET versions (and operating systems if I recall correctly) and is messy to implement anyway.
The second way is trying to programatically find the width and compensate that way, but that still requires digging into the control template (see issues above)
The third is to let the layout engine figure things out for you. You can do this by sharing the column width on columns 2-4, and setting the width of column 1 to "*". Doing this initially will yield undesired results however, because the Expander Header template has no way to set the HorizontalContentAlignment.
With a little of the above mentioned risk, you can fix that by digging around in the template via codebehind, as described here But its still not perfect yet.
Looks like there is a border or margin somewhere. Lets set the BorderThickness of the expander to 0.
UGH! Better - (the whitespace is gone), but there is still a gap between our grid (red with black border) and the green in .NET 4.5. I could not find the source of this gap in a reasonable amount of time, so I just set the Margin of the expander to 0,0,-1,0. This might need to be compensated for inside the expander depending on content, and brings up suppressed memories of CSS hacks (XAML was suppose to be better, wasn't it?)
End Result:
XAML:
<Window x:Class="Sandbox.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="800" SnapsToDevicePixels="True">
<Window.Resources>
<DataTemplate x:Key="StretchedHeaderTemplate">
<Border HorizontalAlignment="Stretch" Loaded="Border_Loaded">
<ContentPresenter Content="{TemplateBinding Content}"/>
</Border>
</DataTemplate>
</Window.Resources>
<Grid Grid.IsSharedSizeScope="True" Margin="15">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="MainLeft"/>
<ColumnDefinition x:Name="MainRight"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Grid.Column="0" Background="AliceBlue">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="100" SharedSizeGroup="Col2"/>
<ColumnDefinition Width="100" SharedSizeGroup="Col3"/>
<ColumnDefinition Width="100" SharedSizeGroup="Col4"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderBrush="Black" BorderThickness="1">
<TextBlock>Col1</TextBlock>
</Border>
<Border Grid.Column="1" BorderBrush="Black" BorderThickness="1">
<TextBlock>Col2</TextBlock>
</Border>
<Border Grid.Column="2" BorderBrush="Black" BorderThickness="1">
<TextBlock>Col3</TextBlock>
</Border>
<Border Grid.Column="3" BorderBrush="Black" BorderThickness="1">
<TextBlock>Col4</TextBlock>
</Border>
</Grid>
<Grid Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" HorizontalAlignment="Center">January</TextBlock>
<TextBlock Grid.Column="1" HorizontalAlignment="Center">February</TextBlock>
<TextBlock Grid.Column="2" HorizontalAlignment="Center">March</TextBlock>
</Grid>
<StackPanel Grid.Column="0" Grid.Row="1">
<Expander HeaderTemplate="{StaticResource StretchedHeaderTemplate}" Background="LightGreen" BorderThickness="0" Margin="0,0,-1,0">
<Expander.Header>
<Grid HorizontalAlignment="Stretch" Background="LightCoral">
<Grid Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition SharedSizeGroup="Col2"/>
<ColumnDefinition SharedSizeGroup="Col3"/>
<ColumnDefinition SharedSizeGroup="Col4"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderBrush="Black" BorderThickness="1">
<TextBlock>Record1</TextBlock>
</Border>
<Border Grid.Column="1" BorderBrush="Black" BorderThickness="1">
<TextBlock>02.05.2016</TextBlock>
</Border>
<Border Grid.Column="2" BorderBrush="Black" BorderThickness="1">
<TextBlock>05.05.2017</TextBlock>
</Border>
<Border Grid.Column="3" BorderBrush="Black" BorderThickness="1">
<TextBlock>340</TextBlock>
</Border>
</Grid>
</Grid>
</Expander.Header>
</Expander>
</StackPanel>
</Grid>
Code Behind:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Border_Loaded(object sender, RoutedEventArgs e)
{
Border root = (Border)sender;
ContentPresenter presenter = (ContentPresenter)root.TemplatedParent;
presenter.HorizontalAlignment = HorizontalAlignment.Stretch;
}
}
Conclusion: This works, but you might want to consider overriding the control template for the Expander if you find any of it too messy.

C# WPF Put children of custom control to specific grid

I have some question in wpf and user control creating.
I have simple Menu control which includes Grid, Image(0 Column) and TextBlock(1 Column).
The promlem Im stucked with is how to put all children of my control to another grid near parent control.
This is demo code of user control:
<UserControl x:Name="userControl" x:Class="Yo.Controls.mItem"
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="50" d:DesignWidth="400">
<Grid x:Name="m_Grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding ActualHeight, ElementName=userControl, Mode=OneWay}"/>
<ColumnDefinition/>
<ColumnDefinition Width="305"/>
</Grid.ColumnDefinitions>
<Image x:Name="img" Grid.Column="0"/>
<TextBlock x:Name="txt" Grid.Column="2"/>
<Grid x:Name="sub_Grid" Visibility="Hidden" Background="#78000000" Margin="-450,0,50,0" MouseLeftButtonUp="img_Check" MouseEnter="grid_Enter" MouseLeave="grid_Leave"/>
</Grid>
Where sub_Grid is the place where children must be placed.
<Controls:mItem Grid.Row="0" Text="Some txt" IsCheckable="False">
<Controls:mItem Text="Its Child" IsCheckable="False"/>
</Controls:mItem>
So this code will place Control with Text Its Child to sub_Grid
I believe you should nest the controls within subGrid and then define columns for the sub grid. I am going on a wimp here by suggesting the following because I don't entirely understand your question:
<Grid x:Name="m_Grid" Background="Red">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
<ColumnDefinition Width="305"/>
</Grid.ColumnDefinitions>
<Grid x:Name="sub_Grid" Background="Blue" Margin="0,0,50,0"
MouseLeftButtonUp="img_Check" MouseEnter="grid_Enter" MouseLeave="grid_Leave" Grid.Column="2">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image x:Name="img" Grid.Column="0"/>
<TextBlock x:Name="txt" Grid.Column="2"/>
</Grid>
</Grid

Height image by heights textblock

I have image and 3 textblock. I want place image left and 3 TextBlock in rows right. I've tried this:
<Grid x:Name="Grid">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Image Grid.RowSpan="3"
Source="image.jpg" Stretch="Uniform" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<TextBlock Grid.Column="1"
Text="11"
FontSize="25"/>
<TextBlock Grid.Column="1"
Grid.Row="1"
Text="22"/>
<TextBlock Grid.Column="1"
Grid.Row="2"
Text="33" FontSize="14"/>
</Grid>
But I have large space between rows when image is big. How I can do this?
If you want the image to remain its size... simply get rid of the grid rows and throw the TextBlocks into a vertical StackPanel.
If you want to resize your image so that it has the same height as the 3 TextBlocks... you can bind the Height of the Image to the ActualHeight of whatever container you put the TextBlocks in, like this:
<Grid x:Name="Grid">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Height="{Binding ActualHeight, ElementName=myStackPanel}" Source="image.jpg" Stretch="Uniform" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<StackPanel Grid.Column="1">
<StackPanel Name="myStackPanel">
<TextBlock Text="11" FontSize="25"/>
<TextBlock Text="22"/>
<TextBlock Text="33" FontSize="14"/>
</StackPanel>
</StackPanel>
</Grid>
I would try to make a grid with 1 row and 2 columns.
In the first column i would place the image.
In the second column i would place a stack panel with vertical flow.
Then add the textblocks to the stackpanel.

Why does my ScrollViewer destroy my Grid Layout? WPF

Problem: When adding a ScrollViwer around a Grid the Grid scaling is cancelled!
Eksampel:
I have created a grid width 3 columns, the 1. coulymn should always be 2 times larger than column 2 and 3!
Without the ScrollViewer this is always true, but when adding it it allows each column to decide its own size.
<Window x:Class="alternatingGridRow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="Auto" Loaded="WindowLoaded">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
<Grid x:Name="LayoutRoot" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="23" MaxHeight="60"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Stretch" Text="sdasdasdasdsadsadasddasdck" TextWrapping="Wrap" VerticalAlignment="Top" />
<TextBlock Foreground="Red" Grid.Column="1" HorizontalAlignment="Stretch" Text="sdasdasdasdsadsadasddasdck" TextWrapping="Wrap" VerticalAlignment="Top" />
</Grid>
</ScrollViewer>
As you can clearly see the scaling factors are completely wrong! As the 2. column is way to large! and the 3. column is some random size...
Wrong Scaling factors
Any advice on this is well recieved....
Cheers Martin
You're asking the grid to assign a percentage of infinite space to each column. Infinite because horizontal scrolling is enabled on your ScrollViewer, and the whole point of ScrollViewers is to virtualize space. So what you're asking it to do doesn't even make sense.
Ok I see your point in why the column sizes a screwed.
But.. I thought of a solution as I read your posts...
As, Mohammed said, set a fixed width on my grid, well.. I want my grid to have same width as scrollviewer unless it gets to small, then I want the scrollviewer to take affect!
So.. my solution is:
MinWidth="500" Width="{Binding ActualWidth, ElementName=scrollviewer}"
<Window x:Class="alternatingGridRow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="Auto">
<ScrollViewer x:Name="scrollviewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
<Grid x:Name="LayoutRoot" ShowGridLines="True" MinWidth="500" Width="{Binding ActualWidth, ElementName=scrollviewer}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="23" MaxHeight="60"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Stretch" Text="sdasdasdasdsadsadasddasdck" TextWrapping="Wrap" VerticalAlignment="Top" />
<TextBlock Foreground="Red" Grid.Column="1" HorizontalAlignment="Stretch" Text="sdasdasdasdsadsadasddasdck" TextWrapping="Wrap" VerticalAlignment="Top" />
</Grid>
</ScrollViewer>
</Window>
(Only fixed for horizontal)
Thx.
The current setup is wrong, because the ScrollViewer does not limit the width and height of its child (i.e. unlimited), moreover, the Grid always fills all the available horizontal and vertical space available on its parent container, and that is why you see this weird behavior. You have to do one of the followings:
either, remove the ScrollViewer as you mentioned.
or, set a fixed height and width for your Grid.

Silverlight Grid - Stretch to parents containersize but do not expand to acommodate children

Is there any way to make a silverlight/wpf grid stretch to its parent width/height (using auto) but do no expand to acommodate children? In a Silverlight application I have the following:
Main Page, with a Frame:
<ScrollViewer x:Name="LayoutRoot" BorderThickness="0" Padding="0" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Background="{StaticResource DefaultBackgroundBrush}" BorderBrush="{StaticResource DefaultBorderBrush}" BorderThickness="0,0,0,1">
<!--Some header content-->
</Border>
<sdk:Frame x:Name="Frame" Grid.Row="1" UriMapper="{StaticResource UriMapper}" ContentLoader="{StaticResource ContentLoader}" BorderThickness="0" />
</Grid>
</ScrollViewer>
In this frame I load the desired page:
<navigation:Page
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:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="MyNamespace.MyPage" mc:Ignorable="d"
d:DesignWidth="640" d:DesignHeight="480"
Title="{StaticResource PageTitle}">
<Grid x:Name="LayoutRoot">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel d:LayoutOverrides="Width" Visibility="Collapsed">
<!-- Some header content -->
</StackPanel>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock TextWrapping="Wrap" Text="Titletext" FontSize="13.333" FontWeight="Bold" d:LayoutOverrides="Height"/>
<RichTextBox BorderThickness="0" IsReadOnly="True" Background="{x:Null}" BorderBrush="{x:Null}" VerticalScrollBarVisibility="Auto" Grid.Row="1" Padding="0">
<Paragraph><Run Text="Text that will force the grid to expand."/></Paragraph>
</RichTextBox>
</Grid>
</Grid>
</Grid></navigation:Page>
The frame in the main page is designed to deal with its content overflow ( through the scrollviewer), because a I have some pages that demand a minimum size.
The grid that holds the text box stretches to the parent, but when I put a large text inside the text box the grid resizes to the width of the text, making the horizontal scroll bar of the frame's scrollviewer appear. I'm looking for a solution that doesn't require binding the max size of the grid to the max size of its parent ( this wouldn't work without hacks in Silverlight anyway, since binding to ActualWidth/Height is bugged). Any ideas?
You just have to change the wrapping like already posted AND change one property of the ScrollViewer:
ScrollViewer.HorizontalScrollBarVisibility="Auto"
to
ScrollViewer.HorizontalScrollBarVisibility="Disabled"

Categories

Resources