WPF: Trigger a content resize with GridSplitter - wpf

I'm trying to force a grid/expander to reevaluate whether it needs a scrollbar, as it's showing emptiness.
I'm using this layout:
<Grid>
<toolstrip /> <!-- fixed height row -->
<Scrollviewer> <!-- * height -->
<Grid> <!-- all rows are 'Auto' height -->
<Expander />
<Expander> <!-- this one stretches far too high -->
<WPF Toolkit: DataGrid />
<Expander>
<GridSplitter/>
<Expander />
<Grid>
</Scrollviewer>
<stackpanel /> <!-- fixed height row -->
<Grid>
The DataGrid (WPF Toolkit) is bound to a property when the Window is initialized. Through some investigating, I've realized that when the window is initialized, the columns in the GridView start at about 10 pixels wide, then the content is added, then they're resized based on the sizes in the XAML (All using star widths - eg: 2*). This causes the grid to resize to about 6 times the height it needs to be as the window is showing, then it doesn't spring back and the only way to see what's at the bottom of the window is to either scroll or move the GridSplitter back up to where it should be and resize the Window. I haven't set the VerticalAlignment properties on anything.
So far I've tried all of the following called InvalidateArrange(), InvalidateVisual();, InvalidateMeasure() and UpdateLayout() on the problem expander and InvalidateArrange(), InvalidateScrollInfo(), InvalidateVisual() and UpdateLayout() on the Grid above it but it won't shrink back.
Is there any way I can force it to short of forcing the width of the columns in the DataGrid?

Try setting these properties on the ScrollViewer:
<ScrollViewer CanContentScroll="True"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto">
... content ...
</ScrollViewer>
If that doesn't work, can you provide a more exact representation of your XAML. Also, taking a look at the ScrollViewer in depth may help.

Related

StackPanel interferes with sizing by margin

I have an app with a TabControl. On each TabItem is a DataGrid. The width and height are not set, the sizing is controlled by the margin so it sizes along with the tab.
<TabItem Name="tbRails" Header="Rails">
<DataGrid x:Name="dgRails" Margin="5,30,5,5" ItemSource=...
This is all working fine until I needed to put a CheckBox on one of the tabs. We can only have one child on a TabItem so I added a StackPanel and put in the CheckBox and the DataGrid.
<TabItem Name="tbRails" Header="Rails">
<StackPanel Name="pnlRails" Margin="10">
<CheckBox Name="chkCollapseItems" Content="Collapse Items" Margin="15" Checked="chkCollapseItems_Checked" ... />
<DataGrid x:Name="dgRails" Margin="5,30,5,5" ItemSource=...
After doing this the data grid has no scrollbar and doesn't respond to mouse wheel. I can click on the cell and it gets selected and I can arrow key down until it disappears out of the bottom. The width sizes to the window just like it did before but it appears to be sizing its height to fit the content (about 2600 rows).
Has anyone seen this before and how do we fix it? I can set the height of the grid and it works just fine but it no longer sizes itself to match the parent.
Use a Grid as panel instead of a StackPanel. A stack panel will measure its children with positive infinity, which does not restrict their height. In other words, the DataGrid will be scaled to display all its records and therefore there will be no scroll viewer.
Using a Grid with the RowDefinitions below, the CheckBox will size to fit its content and the DataGrid will get the rest of the available space in the TabItem.When this available space is not enough to display all records, it will automatically display a scrollbar.
<TabItem Name="tbRails" Header="Rails">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<CheckBox Grid.Row="0" Name="chkCollapseItems" Content="Collapse Items" Margin="15" Checked="chkCollapseItems_Checked" ... />
<DataGrid Grid.Row="1" x:Name="dgRails" Margin="5,30,5,5" ItemSource= ... />
</Grid>
</TabItem>

WPF UserControl fill ContentControl with fixed width and height

I have UserControls that I want to display in a ContentControl. So what I did(this is just one UserControl I have more):
<UserControl.Resources>
<DataTemplate x:Key="Suburb" DataType="{x:Type local:ViewSuburb}">
<local:ViewSuburb Width="Auto" Height="Auto" />
</DataTemplate>
</UserControl.Resources>
<ContentControl Grid.Column="1" Grid.Row="1" ContentTemplate="{StaticResource Suburb}">
</ContentControl>
(The ViewSuburb Width="Auto" Height="Auto" has no effect)
My problem is that the ViewSuburb is only used as a popup dialog thus in its .xaml I gave it a fixed width and height. If I set the width and height to auto then it is fine in the ContentControl and stretches accordingly but it stretches the popup over the screen. Since I gave it the fixed width and height the popup is fine but in the ContentControl it also has the fixed width and height.
Is there a way I can override the width and height of the SuburbView or if I set it to auto that the popup wouldn't stretch across the screen?
Thanks.
You should set the Width/Height of the Popup/Window that is the parent of the ContentControl.

WPF DataGrid MaxWidth set to 100% availiable space

I've got unusual problem that I can't solve. I want to use DataGrid with fixed column sizes that will size up to parent. Structure looks more less like this:
UserControl put on ScrollViewer sizes correctly to parent unless it reaches MinWidth then scrollbar appears. All controls on UserControl are stretched when someone resize window. Only individual is DataGrid. It doesn't want to enable horizontal scroll no matter how much I try it always makes UserControl scale to it's width. This of course enables scroll under UserControl which I want to prevent.
in short I want DataGrid to take up 100% of available width but not more.
<Window>
<ScrollViewer>
<UserControl>
<Grid>
<DataGrid>
</DataGrid>
</Grid>
</UserControl>
</ScrollViewer>
</Window>
I also tried to do something like that, but it failed :(
<Window>
<ScrollViewer>
<UserControl>
<Grid>
<ScrollViewer>
<DockPanel>
<DataGrid>
</DataGrid>
</DockPanel>
</ScrollViewer>
</Grid>
</UserControl>
</ScrollViewer>
</Window>
Also hooking up to SizeChanged and initially setting Width of DataGrid to some small fixed value event did not make the test. Probably because I'm operating on UserControl derived code.
I need suggestions.
Get rid of the ScrollViewer around the DataGrid entirely, that will cause the DataGrid to not know the width of its parent control - it tells the DataGrid that it has infinite space.
Just try placing the DataGrid as in your first example, and setting HorizontalAlignment=Stretch on the DataGrid. That should be the default on the Grid containing the DataGrid, but set it there too just to be sure. Also make sure you don't have the width property set (MinWidth should be fine).
Edit your code into your question once you've given it a shot.

WPF/Silverlight XAML Stretch Text Size to Fit container?

I've just started to play with WPF.
Is it possible to have the size of the text of a Label or TextBlock size itself to fill it's parent container?
Thanks,
Mark
You can use a ViewBox to visually zoom something to fit within its container. The other solutions here work, but they only stretch the control, not its content. The ViewBox will stretch both.
<!-- Big grid, will stretch its children to fill itself -->
<Grid Width="1000" Height="1000">
<!-- The button is stretched, but its text remains teeny tiny -->
<Button>
<!-- The viewbox will stretch its content
to fit the final size of the button -->
<Viewbox
Margin="4"
VerticalAlignment="Stretch"
Height="Auto">
<!-- The textblock and its contents are
stretched to fill its parent -->
<TextBlock
Text="Bartenders" />
</Viewbox>
</Button>
</Grid>
Depends on the parent container
Grid, DockPanel will stretch your control
StackPanel, WrapPanel will leave it to the control to size itself..
Set HorizonalAlignment/VerticalAlignment to "stretch".
Use DockPanel as parent container
<DockPanel>
<TextBlock />
</DockPanel>

How can I get a vertical scrollbar in my ListBox?

In the example below I have a ListBox with dozens of font names in it.
I would have thought it would automatically have a vertical scrollbar on it so that you can select ANY font, not just the first ones in the list, but it doesn't.
So I added a "ScrollViewer" and that puts a "scrollbar area" on the right but there is no scrollbar in the scrollbar area so that you can scroll (!).
Why isn't a scrollbar automatic and how do I force it to have a scrollbar?
<StackPanel Name="stack1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<ScrollViewer>
<ListBox Grid.Row="0" Name="lstFonts" Margin="3" ItemsSource="{x:Static Fonts.SystemFontFamilies}"/>
</ScrollViewer>
</Grid>
</StackPanel>
The problem with your solution is you're putting a scrollbar around a ListBox where you probably want to put it inside the ListBox.
If you want to force a scrollbar in your ListBox, use the ScrollBar.VerticalScrollBarVisibility attached property.
<ListBox
ItemsSource="{Binding}"
ScrollViewer.VerticalScrollBarVisibility="Visible">
</ListBox>
Setting this value to Auto will popup the scrollbar on an as needed basis.
ListBox already contains ScrollViewer. By default the ScrollBar will show up when there is more content than space. But some containers resize themselves to accommodate their contents (e.g. StackPanel), so there is never "more content than space". In such cases, the ListBox is always given as much space as is needed for the content.
In order to calculate the condition of having more content than space, the size should be known. Make sure your ListBox has a constrained size, either by setting the size explicitly on the ListBox element itself, or from the host panel.
In case the host panel is vertical StackPanel and you want VerticalScrollBar you must set the Height on ListBox itself. For other types of containers, e.g. Grid, the ListBox can be constrained by the container. For example, you can change your original code to look like this:
<Grid Name="grid1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Name="lstFonts" Margin="3"
ItemsSource="{x:Static Fonts.SystemFontFamilies}"/>
</Grid>
</Grid>
Note that it is not just the immediate container that is important. In your example, the immediate container is a Grid, but because that Grid is contained by a StackPanel, the outer StackPanel is expanded to accommodate its immediate child Grid, such that that child can expand to accommodate its child (the ListBox).
If you constrain the height at any point — by setting the height of the ListBox, by setting the height of the inner Grid, or simply by making the outer container a Grid — then a vertical scroll bar will appear automatically any time there are too many list items to fit in the control.
I added a "Height" to my ListBox and it added the scrollbar nicely.
Scroll Bar is added to the List box automatically unless its visibility is set to Hidden. Whenever the size of List Items exceeds the one, which can be shown inside a list box vertical or horizontal list box can be seen during the run time.
In my case the number of items in the ListBox is dynamic so I didn't want to use the Height property. I used MaxHeight instead and it works nicely. The scrollbar appears when it fills the space I've allocated for it.
I was having the same problem, I had a ComboBox followed by a ListBox in a StackPanel and the scroll bar for the ListBox was not showing up. I solved this by putting the two in a DockPanel instead. I set the ComboBox DockPanel.Dock="Top" and let the ListBox fill the remaining space.
XAML ListBox Scroller - Windows 10(UWP)
<Style TargetType="ListBox">
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Visible"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Visible"/>
</Style>

Resources