WPF Grid with a dynamic number of columns - c#

I am quite new to WPF, and am struggling with accomplishing a visual effect - I would like to have a two-dimensional grid of objects with a data-driven number of columns. I am trying to go with MVVM with zero code-behind. I have had a look at several posts in this regard, and have come up with the following:
<UserControl x:Class="Demo.Views.SideBySideStackPanelView"
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"
xmlns:views="clr-namespace:Demo.Views"
xmlns:viewModels="clr-namespace:Demo.ViewModels"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<DataTemplate x:Key="ColumnTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="400"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" SharedSizeGroup="TreeView"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" SharedSizeGroup="DetailView"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0" LastChildFill="True">
<TextBlock Text="{Binding Name}" DockPanel.Dock="Left"/>
<Button Command="{Binding Close}" DockPanel.Dock="Right" HorizontalAlignment="Right">
<Image Width="10" Height="10" Source="/Demo;component/Images/Close.png" />
</Button>
</DockPanel>
<views:TreeView Grid.Row="1"/>
<GridSplitter
ResizeDirection="Rows"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Height="5"
Grid.Row="2"
Name="sideBySideSplitter"/>
<views:TreeDetail Grid.Row="2"/>
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid d:DataContext="{d:DesignInstance viewModels:MainWindowViewModel}" Grid.IsSharedSizeScope="True">
<ItemsControl ItemsSource="{Binding PluginItem}" ItemTemplate="{StaticResource ColumnTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</UserControl>
The TreeView view is a basic bound TreeView and the TreeDetail view is a simple bound Grid.
The control does render my content more-or-less as desired, but when I interact with the tree view that is in the upper part of the column the control expands vertically rather than a scroll bar showing up in the tree. The GridSplitter doesn't work at all; in fact it appears to render in the middle of the detail object.
I have a similar DataTemplate in a TabControl.ContentTemplate and it works as desired. Moving the GridSplitter causes scroll bars to show up on either side when necessary and opening up TreeView items causes scroll bars to show up in that control.
What I am after is an Excel-like presentation where the user can control the sizes of the cells with horizontal and vertical "splitters" and the user objects within the cells scroll within the cell as necessary. I can live with fixed-size columns for now.
I would appreciate any help provided. Thanks.

Related

UWP GridView scroll bar never showing up

I have a Page that allow the user to load multiple images thumbnails from his folders.
The number of rows update nicely when the width of the window is changed
The only thing that I could not figure out how to make it work is having the vertical scroll bars, I pretty much tried every settings possible.
At first my root was a stackPanel so I switched to a Grid to see if there would be any difference.
here is my xaml
<Page
x:Class="IMG.Pages.UploadPage"
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:img="using:IMG"
xmlns:local="using:IMG.Pages"
xmlns:Models="using:IMG.Models"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid x:Name="root">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0"
Padding="2"
BorderBrush="Black"
BorderThickness="1"
Orientation="Horizontal">
<Button Click="GetPhoto" Content="get images" />
</StackPanel>
<GridView x:Name="ImageGrid" Width="Auto" Background="LightBlue" Grid.Row="1" Margin="5" Height="Auto"
SizeChanged="ImageGridSizeChanged"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollMode="Auto"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollMode="Disabled">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate x:Name="ImgThumbnail" x:DataType="Models:ImageData">
<StackPanel
Width="100"
Height="120"
Margin="5"
AutomationProperties.Name="{x:Bind Hash}">
<StackPanel Margin="1">
<TextBlock Text="{x:Bind File}" />
</StackPanel>
<Image x:Name="thumbIMG" Width="80" Height="100" Stretch="UniformToFill" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
At first the gridview is empty, the user click on the button and then in the FileOpenPicker he can choose multiple images and they are added as thumbnail binded to an ObservableList of ImageData
The binding work nicely, I am simply stuck on the scrollbar
I have experienced the same issue and I fixed it by setting the height of the gidview on the fix size instead of auto. And than you can set
ScrollViewer.VerticalScrollBarVisibility = "Visible"
ScrollViewer.VerticalScrollMode = "Enable"

Textbox Filling all available space in Grid Row

I'm experiencing a problem with my UI XAML code. The problem is that I can't get my TextBox to fill in all available space in the Grid Row that contains it. I read quite a few posts about similar issues, and the summary of them is "don't use stack panel for this" and "set VerticalAlignment="Stretch"", but this did not work for me. Near the bottom of my XAML you can see the text box that I've been trying to get to stretch to fill the height of the grid row, along with the text box I'm hoping to have work by the end in a comment.
Having VerticalAlignment="Stretch" does not change the behavior of the XAML, and produces a one-line TextBox as if I didn't assign VerticalAlignment="Stretch" at all. This is what the GUI page looks like with or without VerticalAlignment="Stretch":
Here is the respective XAML code.
<ContentControl x:Class="Analytics.Configuration.UI.DataflowTemplateView"
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"
xmlns:local="clr-namespace:ComputersUnlimited.Analytics.Configuration.UI"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:core="http://schemas.cu.net/2011/xaml/presentation/core"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:DataflowTemplateViewModel, IsDesignTimeCreatable=True}">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" x:Name="Row0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Command="{Binding NavigateToPreviousControlCommand}" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="0,0,20,0">Back</Button>
<TextBlock Grid.Column="1" Text="M-Code Template Text" FontSize="20" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</Grid>
<!--<TextBox Grid.Row="1"
TextWrapping="Wrap"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="0,6,0,6"
AcceptsReturn="True"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"/>-->
<TextBox Grid.Row="1" VerticalAlignment="Stretch"/>
</Grid>
I've tried all the advice I've ran into with no success. So, if you have any advice, sharing would be appreciated.
Thank you.
Most likely there is an implicit style for TextBox that is setting a default Height. If that's the case, you'll need to set:
Height="NaN"
On your TextBox in order for it to stretch.

How to add a Scrollbar in Listbox in a Grid in XAML?

I'm new to XAML and I cant seem to figure this out. I want a two column page that is docked (in winforms term) to its container. The first column has a listbox and I want this to automatically show scrollbar when needed. I was able to do so but only if I set the Height or MaxHeight of the ListBox. My problem with that is the listbox wont grow in size anymore when the main windown/form is resized. What I want is to dock the listbox to the first column so it will resize when the form is resized and show a scrollbar when needed.
Here is the code the does not show a scrollbar:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Grid.Row="0">
<ListBox x:Name="lstView"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Margin="10">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="20">
<TextBlock Text="{Binding}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Grid>
Here is the code that shows a scrollbar but has a fixed height.
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Grid.Row="0">
<ListBox x:Name="lstView"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Height="200"
Margin="10">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="20">
<TextBlock Text="{Binding}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Grid>
The problems with scroll bar visibility when using a StackPanel. I think it is because the StackPanel is always as big as it needs to be to contain all of its children. Try reorganizing the layout to remove the StackPanel (use a Grid instead) and see if that helps.

ListView resizes without respecting the columndefinitions

I have this very simple XAML window:
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<ContentControl Content="{Binding Path=Item}" ContentTemplate="{StaticResource aaaa}" Grid.Row="1"/>
<ListView ItemsSource="{Binding Path=ItemList}" ItemTemplate="{StaticResource aaaa}" HorizontalContentAlignment="Stretch"/>
</Grid>
where the ContentControl and the ListView have the same template:
<DataTemplate DataType="{x:Type src:ItemType}" x:Key="aaaa">
<Grid ShowGridLines="True" Height="30">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Name="resizinglabel" Text="this is a very long text that has to be trimmed" />
<TextBlock Name="fixedLabel" Text="always to the left" Grid.Column="1" Background="Red" />
</Grid>
</DataTemplate>
But when I resize the window the listview seems to have a weird behaviour:
Before the critical point of resizing:
After The critical point of resizing:
in a few words i want the right label to be always visible on the right. I tried also with the isSharedSizeScope property but id doesn't works... So the question is: what I have to do to make the listview behaving like the content control?
Thanks in advance!
ListViews will automatically add ScrollBars if their content is too large to fit on the screen. Disable the Horizontal ScrollBar and it should work.
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled" />

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