Can't get WPF ScrollViewer to work - wpf

I have a StackPanel and for some reason I can't get the content of the ScrollViewer on the very bottom to be scrollable, despite the fact that the internal height of the Frame clearly exceeds the bounds of the ScrollViewer. I previously had a Grid as the root container of the Window, but when I changed it to StackPanel the scrollbar no longer appears.
The only thing that seems to work is if I explicitly set the height of the ScrollViewer, but then it does not size with thw Window when it's resized.
Do I have to use a Grid?
Sorry if this is obvious; I'm relatively new to WPF.
Thanks in advance for any help!
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignWidth="566" Width="719" >
<StackPanel VerticalAlignment="Stretch" >
<Menu HorizontalAlignment="Stretch" Name="Menu1" VerticalAlignment="Stretch" Width="Auto">
<MenuItem Header="_File" Name="MenuItem1">
<MenuItem Header="_Print" Name="MenuItem2" />
</MenuItem>
</Menu>
<Canvas x:Name="SearchCanvas" Width="681" Height="55">
<ComboBox Canvas.Left="6" Canvas.Top="0" Height="22" x:Name="cbLookupField" Width="302" Text="" SelectedIndex="0">
<ComboBoxItem Content="Reference Name" />
<ComboBoxItem Content="Matter" />
<ComboBoxItem Content="Client Loan Number" />
</ComboBox>
<TextBox KeyDown="tbLookup_KeyDown" Canvas.Left="6" Canvas.Top="28" Height="23" x:Name="tbLookup" Width="302" />
<Button Canvas.Left="314" Canvas.Top="27" Content="Search" Height="24" Name="btnSearch" Width="106" />
<ListView MouseDoubleClick="lvSearchResults_MouseDoubleClick"
ItemsSource="{Binding Tables[0]}"
Canvas.Left="-8" Canvas.Top="57" Height="129" Name="lvSearchResults" Width="697" Visibility="Hidden">
<ListView.View>
<GridView x:Name="gvResultsGridView"/>
</ListView.View>
</ListView>
</Canvas>
<ScrollViewer x:Name="ScrollViewer1" VerticalScrollBarVisibility="Visible">
<Frame Height="Auto" Source="Full Report.xaml" VerticalAlignment="Stretch" x:Name="Frame1" />
</ScrollViewer>
</StackPanel>
</Window>

The ScrollViewer in the bottom does not have a fixed height, and therefore because it's contained in a StackPanel, its height will be the height of the content, which in this case is the Frame height.
You can either set a fixed height for the ScrollViewer, or use a Grid instead of a StackPanel. In case you use a grid you should set a fixed height for the row in which the ScrollViewer will be located.
Hope it helps!

Related

How to have a Tab control fill the center of a DockPanel in WPF

I have a WPF Window with a DockPanel that contains a Menu, a TabControl, and a Status Bar. I can get the Menu to dock to the top and the Status Bar to dock to the bottom, but I can't get the Tab control to fill the area between those two controls.
<Window x:Class="MediaCatalog.Window1"
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:local="clr-namespace:MediaCatalog"
mc:Ignorable="d"
Title="Window1" Height="450" Width="800">
<DockPanel LastChildFill="False">
<Menu Width="Auto" VerticalAlignment="Top" HorizontalAlignment="Left"
DockPanel.Dock="Top">
</Menu>
<TabControl DockPanel.Dock="Top" Margin="0,0,0,0"
BorderThickness="1,1,1,1" Height="291">
</TabControl>
<StatusBar DockPanel.Dock="Bottom" Height="22">
<StatusBar/>
</StatusBar>
</DockPanel>
The last element will fill the DockPanel unless you set LastChildFill to false:
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="A" />
<MenuItem Header="B" />
</Menu>
<StatusBar DockPanel.Dock="Bottom" Height="22" />
<TabControl Margin="0,0,0,0" BorderThickness="1,1,1,1">
<TabItem Header="A" />
<TabItem Header="B" />
</TabControl>
</DockPanel>
Note that you shouldn't set the DockPanel.Dock attached property of the last element.
Also, you don't want to specify a default Height for the TabControl if you want it to fill the remaining space.
The above sample markup will make the TabControl fill the remaining space between the top Menu and the bottom StatusBar:

WPF window resizing and ActualWidth / ActualHeight values

In my WPF project, I have a Canvas in which I do some drawings. Following the code for the Window:
<Window x:Name="PropertyDefinition_Window" x:Class="PushOverStraus7.PropertyDefinitionWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="PropertyDefinitionWindow" Height="360" Width="730" Loaded="Window_Loaded">
<Grid>
<TreeView SelectedItemChanged="Treeview_PropertyDefinition_SelectedItemChanged">
<TreeViewItem IsExpanded="True">
<TreeViewItem />
</TreeViewItem>
<TreeViewItem>
<TreeViewItem"/>
</TreeViewItem>
</TreeView>
<Canvas x:Name="Canvas_LongitudinalBarRectanglePage" HorizontalAlignment="Left" Height="251" Margin="255,10,0,0" VerticalAlignment="Top" Width="285" Background="Black">
</Canvas>
<Button x:Name="NewButton" Content="Nuovo" HorizontalAlignment="Left" Margin="22,277,0,0" VerticalAlignment="Top" Width="45" Click="NewButton_Click"/>
<Button x:Name="DuplicateButton" Content="Duplica" HorizontalAlignment="Left" Margin="85,277,0,0" VerticalAlignment="Top" Width="45"/>
</Grid>
I want that, resizing the Window, the Canvas size changes accordingly. Then, I need to have ActualWidth and ActualHeight of the Canvas resized to use them for drawing alghorithm.
How can I have the automatical resize of the Canvas and how to get values described above?
Thanks for your help
EDIT:
I've changed the question as asked
With the following XAML the Canvas will automatically be resized when the Window size changes.
<Window ...>
<Frame>
<Frame.Content>
<Page>
<Canvas>
...
</Canvas>
</Page>
</Frame.Content>
</Frame>
</Window>

Dock a resizable wpf DataGrid at bottom of window

In a WPF project, I want to dock a DataGrid to the bottom of a window so that if the window resizes, I will be able to utilize more of the DataGrid. Like this:
How do I do that? All my DockPanel attempts have failed.
The current attempt is here:
<Window x:Class="Foo.SQLDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:Foo.Controls"
Title="test" ResizeMode="CanResize" Width="400" Height="400">
<StackPanel Orientation="Vertical" Height="Auto" Width="Auto">
<StackPanel Orientation="Vertical">
<Label Content="SQL" HorizontalAlignment="Left"/>
<TextBox Width="377" Height="100" Name="txtSQL"/>
<Button Content="Run SQL" Click="Button_Click_1" />
</StackPanel>
<Label Content="Result" HorizontalAlignment="Left"/>
<ScrollViewer Width="Auto" Height="180" DockPanel.Dock="Right,Bottom"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto">
<DataGrid x:Name="dataResult" />
</ScrollViewer>
</StackPanel>
</Window>
The height of the scrollviewer+datagrid will not adapt however.
First of all, using DockPanel.Dock without having a DockPanel as a parent doesn't do much...
In my example I changed your root StackPanel to a DockPanel so it will work as you want.
I also used DockPanel.LastChildFill property which makes sure the last child of the DockPanel will get all the remaining space:
<DockPanel LastChildFill="True">
<StackPanel Orientation="Vertical" DockPanel.Dock="Top">
<Label Content="SQL" HorizontalAlignment="Left"/>
<TextBox Width="377" Height="100" Name="txtSQL"/>
<Button Content="Run SQL" Click="Button_Click_1" />
</StackPanel>
<Label Content="Result" HorizontalAlignment="Left" DockPanel.Dock="Top"/>
<ScrollViewer DockPanel.Dock="Bottom,Right"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto">
<DataGrid x:Name="dataResult" />
</ScrollViewer>
</DockPanel>
Finally, to make it really stretch on all the remaining space, I removed the Height property you set, as this blocked it from stretching.
Not sure if useful or if i understand you question the right way but have you tried this:
<DataGrid DockPanel.Dock="Right, Bottom" VerticalAlignment="Bottom" HorizontalAlignment="Right" ></DataGrid>

How to make a ListView inside a grid in WPF fill the whole screen, even when resized

I have a control which is a grid where the first row contains some buttons, with fixed height, and the second (and last) row contains a ListView. Then I have a main screen which contains only a menu and this user control above. I would like to have the size of the ListView as the maximum for the window, which means that if the window is maximized the ListView will be large, in case the window is smaller, so is the ListView (with vertical scroll to help navigating through items).
This is how I am doing it:
Window:
<Window x:Class="TestUI.MainView"
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"
mc:Ignorable="d"
Width="auto" Height="auto"
MinHeight="300" MinWidth="300"
Title="Test"
DataContext="{Binding MainViewModel, Source={StaticResource Locator}}" >
<StackPanel Orientation="Vertical" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<DockPanel>
<Menu DockPanel.Dock="Top" >
<MenuItem Header="Item 1" Command="{Binding Command1}"/>
<MenuItem Header="Item 2" Command="{Binding Command2}"/>
<MenuItem Header="Item 3" Command="{Binding Command3}"/>
</Menu>
</DockPanel>
<DockPanel LastChildFill="True">
<ScrollViewer Content="{Binding Content}" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled" DockPanel.Dock="Bottom" />
</DockPanel>
</StackPanel>
</Window>
User Control:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="35" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="5, 5, 5, 5" Orientation="Horizontal">
<Button Content="New" Width="60" Command="{Binding NewCommand}"/>
<Button Content="Remove" Width="60" Margin="10, 0, 0, 0" Command="{Binding RemoveCommand}" />
</StackPanel>
<DockPanel Grid.Row="1" Margin="5,5,5,5" LastChildFill="True" HorizontalAlignment="Stretch">
<ListView x:Name="ListView" SelectionMode="Single" DockPanel.Dock="Top" ItemsSource="{Binding Entities}" SelectedItem="{Binding SelectedEntity}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" VerticalAlignment="Stretch">
<ListView.View>
<GridView>
<GridViewColumn Width="auto" Header="Product" DisplayMemberBinding="{Binding Description}"/>
</GridView>
</ListView.View>
</ListView>
</DockPanel>
</Grid>
Could you please help me?
Thank you!
I've just inspected your User Control and the Listview docking is working just fine. You can verify layout in the designer by using background colours. Setting the listview's background to blue shows it is using the available space.
I believe the problem is with the layout in your main form, specifically the Stackpanel. These are notorious for layout issues, and from what I can tell you don't need it. use the DockPanel as the high-level container rather than multiple dock panels. (This is what they're for)
<DockPanel>
<Menu DockPanel.Dock="Top" >
<MenuItem Header="Item 1" Command="{Binding Command1}"/>
<MenuItem Header="Item 2" Command="{Binding Command2}"/>
<MenuItem Header="Item 3" Command="{Binding Command3}"/>
</Menu>
<ScrollViewer Content="{Binding Content}" VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Disabled" DockPanel.Dock="Fill" />
</DockPanel>
This will put your menu at the top of the panel, and let your scroll viewer containing the user control (assumed) use up the remaining available space.
Stack-panels are only good for arranging items within an area. If you want to use layout to allocate available space, use DockPanels or Grids.
Hi remove Width="Auto" from GridviewColumn. I hope this will help

Prevent manual scrolling of a ScrollViewer

I have a ScrollViewer which wraps a bunch of dynamically created TextBox controls. The HorizontalScrollBarVisibility and VerticalScrollBarVisibility are both set to Hidden. I am programmatically scrolling the ScrollViewer in response to the user scrolling a gridview.
The problem i am having is that when the user places the focus on one of those TextBox elements and then presses the left/right arrow keys, the ScrollViewer is scrolling. I want to prevent this manual scrolling and only allow programmatic scrolling. Obviously disabling the ScrollViewer is not an option as the user needs to be able to add text to the TextBoxes inside it. Similarly, setting the HorizontalScrollBarVisibility property to Disabled doesn't work, as that resets the scroll offset back to zero.
How can i lock scrolling, or prevent manual scrolling?
By removing manual operation of the scroll bars, and hiding them, you are basically saying you want something that has a list of items, that can be scrolled from code, but is not a ListBox...
Conclusion: Don't use a ListBox :)
As you are managing the scrolling yourself, why not parent the TextBoxes under a StackPanel within a canvas (with a clipping rectangle of course). Then use the Canvas.Top/Left properties on the StackPanel to scroll it.
The example below does that. I added a slider bound to the Canvas.Top property so you can test it.
Xaml Example:
<UserControl x:Class="SilverlightApplication1.NotAListbox"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Canvas Background="Aquamarine" HorizontalAlignment="Center" Name="canvas1" VerticalAlignment="Center" Width="200" Height="200">
<Canvas.Clip>
<RectangleGeometry Rect="0,0,200,200"></RectangleGeometry>
</Canvas.Clip>
<StackPanel Canvas.Top="{Binding ElementName=slider1, Path=Value}" Name="stackPanel1">
<TextBox Height="23" Text="textBox 1" Width="120" />
<TextBox Height="23" Text="textBox 2" Width="120" />
<TextBox Height="23" Text="textBox 3" Width="120" />
<TextBox Height="23" Text="textBox 4" Width="120" />
<TextBox Height="23" Text="textBox 5" Width="120" />
<TextBox Height="23" Text="textBox 6" Width="120" />
<TextBox Height="23" Text="textBox 7" Width="120" />
<TextBox Height="23" Text="textBox 8" Width="120" />
<TextBox Height="23" Text="textBox 9" Width="120" />
</StackPanel>
</Canvas>
<Slider Height="171" HorizontalAlignment="Center" Margin="316,62,57,66" Name="slider1" VerticalAlignment="Center" Width="27" Orientation="Vertical" Minimum="-223" Maximum="200" />
</Grid>
</UserControl>

Resources