WPF XAML ListView with ScrollBars - wpf

I have a ListView which is showing both scroll bars. To achieve that, I places my ListView within a Border located in a Grid like below:
<Window ...
MinWidth="600" MinHeight="500" Width="800" Height="500"
Topmost="True"
WindowStartupLocation="CenterScreen"
SizeToContent="Height" WindowStyle="None">
<Window.Resources>
<ResourceDictionary>
...
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" MinHeight="60"/>
<RowDefinition Height="48"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="370"/> <-- THIS IS HARDCODED TO 370 BUT I NEED IT TO BE RESIZABLE
</Grid.RowDefinitions>
<Grid Margin="5,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4"/>
<ColumnDefinition Width="346*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding MyName}" Grid.Column="1"
Style="{StaticResource MyNameStyle}" Margin="0,5,0,5" />
</Grid>
<Border BorderBrush="{StaticResource MyBrush}" Grid.Row="1" Grid.Column="0" >
<ListView
x:Name="lstMyListView"
Margin="0,0,0,0"
BorderBrush="Transparent"
ItemsSource="{Binding MyItems}"
SelectedIndex="0"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto">
...
...
</ListView>
...
...
</Border>
...
...
</Grid>
</Grid>
</Window>
This is all in a form that is resizable. Therefore, the ListView should also resize but it should do that only when user resizes the form. The problem with my hard coded value above is obvious, the ListView will not resize but stay at constant height=370.
I know I can set this to 370* but in that case, my List will resize to fit all items. I want to limit this so that resizing only occurs when user resizes the form. So, ListView should show scroll bars if there are more items and as the user resizes form, that scroll bar should go away if form is resized to height that can accommodate all items in ListView.
UPDATE:
Instead of hard coding the height to 370 above, I have tried setting the height to , Auto, and 370. All of these would expand the ListView (and therefore form, too) to accommodate all items in the ListView.
UPDATE 2:
Updated XAML to show whole tree structure.
UPDATE 3:
As per Rachel's suggestion, set hardcoded 370 to "*" in commented line above in XAML and that produces form resized so that the ListView fits all items in it. I added screenshot showing the form as it opens and a screenshot showing how it should look like when it opens. As you can see, it resizes hightwise to accomodate all itesm.
What I need is that form and ListView stay in their set size and resize only if user resizes the form.

If I understand your question correctly, you are saying the form loads as too large of a size because the ListView is growing to it's full height. If that's the case, remove the SizeToContent="Height" from the <Window> tag since it is making the window's initial height be equal to whatever height the content is, which includes the fully sized ListView.

By setting ScrollViewer.VerticalScrollBarVisibility="Visible" & MaxHeight="700"
scroll bar will be visible
MaxHeight to any value

Hi I think i have understand you. So, i am trying:
So, you want to have your ListView at least a height of 370 and then only resizes if the window resizes (increment and decrement of window size).
Setting MinHeight of 2nd RowDefinition could help
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition MinHeight="370"/> <!-- THIS IS HARDCODED....-->
</Grid.RowDefinitions>
.....
</Grid>
Thank you.

Related

Grid width "*" not behaving as expected when parent size is not defined

I have a set of controls in a dialog box that I want to auto-size. Everything worked fine until I tried to re-arange things using an evenly spaced Grid width.
Here's the XAML:
<Grid Margin="20" >
<Grid.RowDefinitions>
<RowDefinition Height="AUTO" />
<RowDefinition Height="AUTO" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid>
...left controls
</Grid>
<Border BorderThickness="1" BorderBrush="Gray" Grid.Column="1" Margin="0,10,0,5">
...right controls
</Border>
<Grid Grid.Row="2" Grid.ColumnSpan="2>
...okay and cancel
</Grid>
</Grid>
Here's the result:
Not what I'm expecting. The right column has a tiny width, for some reason it's not listening to the "*" and making it equal to the half the other column.
If I put a Width="450" on the highest Grid, or UserControl (or during runtime, resize the window it sits in!) Everything "jumps" and I get what I'm expecting, both columns evenly spaced:
But now it doesn't respond to re-sizing, or auto-size for larger content (except that wouldn't stretch when the parent container stretched) If I were after equal spacing I could use a shared size group. Is there anything I'm doing wrong or is this expected behavior for Width="*"?
When your outer Grid is hosted in a container where the width is not defined, the actual width will be the result of the descendant. That is, the (outer) Grid measure pass will "ask" to the right column (the Border): "I'm giving you whatever space you want: how much do you need?". As long the Border fragment won't require any specific size, the result is the default (zero, in most cases). Hence the collapsed behavior.
Basically, you should either define the outer Grid width, or the 2nd column width (by mean anything within the column should tell how much space it needs).
You are right * means to take size proportional to grid. It happens cause your the highest Grid does not enough space to be wider( when you set Width="450", then the Grid becomes wider).
If you have just one grid inside your Window, then the theSecondColumn will take all place at the right side(it will be wider as you want):
<Window x:Class="DataGridAddedColumns.MainWindow"
<!-- The code is omitted for the brevity -->
Title="MainWindow" Height="550" Width="525"
WindowStartupLocation="CenterScreen">
<Grid Name="grid">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Name="theSecondColumn" Width="*"/>
</Grid.ColumnDefinitions>
<Grid>
</Window>

wpf popup wrong placement wrong size

The Popup I am trying to create is in the wrong size and t doesn't seem to care about the placement I've set at all.
<Popup Name="mypopup" Width="700" Height="600" IsEnabled="True" HorizontalAlignment="Center" VerticalAlignment="Top" >
<Grid Background="#FFFFFFF1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.606*"></ColumnDefinition>
<ColumnDefinition Width="0.394*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="70"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
</Grid>
</Popup>
Popup usually does not add as a visual child. Instead it appears in air without any connection with visual. So I suggest you to use HorizontalOffset and VerticalOffset attributes to position the popup. Also there is PlacementMode option to position the popup.
Anatomy of Popup
Regarding the popup size, I suggest to set size to the immediate child (Grid in your case) inside popup instead of setting height and width to popup.

How to add a buttom that is always visible after a scrollviewer?

I have a ScrollViewer which includes a lot of content (datagrids, stackpanels, textboxes, labels, etc...), and outside of it I want to add a button (PRINT), and it is important that the button is not part of the ScrollViewer. My goal is that the top 90% of my screen is the scrollviewer and the bottom 10% is a "frozen panel" that always shows the PRINT button, and this should remain true when maximized and minimized.
After having a lo of problems with 'the property content is set more then once' I realized I need to add both my ScrollViewer and the Button inside another container, so far the only one that seems to work is GRID - but honestly after you read this if you have anything else to recommend I am open to suggestions, I only used GRID because it seemed to almost give me what I wanted.
This is my code right now:
[Code]
<Window DataContext="{Binding PrintView, Source={StaticResource Locator}}" Width="900">
<Grid Height="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollViewer Name="PrintView" Grid.Row="0" Height="Auto">
<StackPanel>
... a LOT of stuff ...
</StackPanel>
</ScrollViewer>
<Button Content="Print"
Margin="0,20,0,20"
Height="50"
Width="150"
FontSize="24"
FontWeight="Bold"
Grid.Row="1"
/>
</Grid>
</Window>
[Code]
When done like this my ScrollViewer doesn't have a Scrollbar so I see the first page but I cannot scroll down, also there is no PRINT button seen
One interesting test was to change the following:
<ScrollViewer Name="Apercu" Grid.Row="0" Height="600">
Now I see my scrollbar again (and I can scroll) and my PRINT button is beneth it and always visible (this is almost perfect) but when I maximumize my window the ScrollViewer stays 600 of height and as such well it doesn't acctually maximize (everything below the PRINT button is just white).
Any ideas? Is there another way I could specify my HEIGHTS or is there a different control I should be using (not GRID)?
Thanks,
Found it ...
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
And remove height from ScollViewer

WPF: Star in ColumnDefinition not expanding columns

I have a user control that need the 1st and 3rd column to have the same width at all time.
My code is a follows:
<UserControl x:Class="UserControls.ListBoxSelector"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListBox x:Name="ListBox_Source" Grid.Column="0" Grid.Row="0" />
<StackPanel Grid.Column="1" Grid.Row="0" Orientation="Vertical">
<Button Content=">" Click="Button_Add_Click"/>
<Button Content="<" Click="Button_Remove_Click" />
</StackPanel>
<ListBox x:Name="ListBox_Destination" Grid.Column="2" Grid.Row="0" />
</Grid>
</UserControl>
The result is not as expected as column 3 (ListBox_Destination) is not expanded at all.
Isn't the 5* in ColumnDefinition enough to force the 2 listbox to the same width??
UPDATED : Sorry that I forgot to mention that the problem only occurs when I put the control inside a RibbonGroup using Microsoft Ribbon for WPF
Sometimes, when you put your control in certian types of layout controls (like a StackPanel), it won't size as expected because the parent layout will only size the child to it's minimum desired size (just enough to show the content). This may be why you are seeing this when you put it in the RibbonGroup. Try giving your Grid a Width or MinWidth and see if that makes a difference.
yes it forces the columns 1 and 3 to be of the same size, but it doesnt gaurentee the content (listboxes) inside the colulms will be of the same size. You have to set the size of content to take up whole space

in wpf how do i make a datagrid fit the window height

I have a grid with 3 columns and 2 rows
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
I the lower left cell, i have a data grid, with AutoGenerateColumns=True which can load many rows. What I want to do is for the data grid height to maximize to fit the window, and for the user to be able to use the datagrid scrollbar to scroll the rows up and down.
What happens is that the datagrid flows of the bottom of the window, and even if i set the
ScrollViewer.VerticalScrollBarVisibility="Visible"
of the datagrid, the scrollbar has no effect and the rows flow downwards. Somehow the datagrid does not feel restricted...
What to do?
Try setting your DataGrid's HorizontalAlignment=Stretch and VerticalScrollBarVisibility=Auto
If that doesn't work, you may also need to bind the Grid's Height to the Window Height so that it doesn't auto-grow to fit its contents. Usually I use Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=ActualHeight}" (It might be RenderSize.ActualHeight instead of just ActualHeight... I forgot.
Another alternative is to use a DockPanel instead of a Grid since that control doesn't auto-grow to fit its contents. Instead it'll stretch its last child to fill the remaining space.
I had the same problem but binding to the Window height did not completely solve the problem for me. In my case the DataGrid still extended 2 to 3 inches below the Window's viewable area. I believe this was because my DataGrid started about 2 to 3 inches below the top of the Window.
In the end I found that it was not necessary to bind the DataGrid's height at all. All I had to do was change the DataGrid's direct container.
For me, the following XAML setup causes the DataGrid to extend beyond the size of the Window when enough rows are added. Notice that the DataGrid sits within a StackPanel.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="75"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<!-- StackPanel Content accounting for about 2-3 inches of space -->
</StackPanel>
<!-- DataGrid within a StackPanel extends past the vertical space of the Window
and does not display vertical scroll bars. Even if I bind the height to Window
height the DataGrid content still extends 2-3 inches past the viewable Window area-->
<StackPanel Grid.Row="1">
<DataGrid ItemsSource="{StaticResource ImportedTransactionList}"
Margin="10,20,10,10" MinHeight="100">
</DataGrid>
</StackPanel>
</Grid>
However, simply removing the StackPanel fixed the problem for me.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="75"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<!-- StackPanel Content accounting for about 2-3 inches of space -->
</StackPanel>
<!-- Removing the StackPanel fixes the issue-->
<DataGrid Grid.Row="1" ItemsSource="{StaticResource SomeStaticResource}"
Margin="10,20,10,10" MinHeight="100">
</DataGrid>
</Grid>
As the original post is quite old, I should note that I am using VS2017 and .Net Framework 4.6.1 but I am not sure if this has any bearing.
You have to define the column and row where the DataGrid is with *.
You say it is on the lower left cell. The row is ok but your column there has Width="Auto".
The AutoGenerateColumns=True gives a mess if Width="Auto".

Resources