Is it possible to have a VariableSizedGridView with virtualization? - c#

I am creating a Windows Phone 8.1 (WinRT) application. The mainpage template is a two GridView (2 grids per row) and the height of grid varies (one item might occupy one row and other might occupy two rows). The design is similar to the pinterest app (pin.it) except the varying height in pinterest app. I was able to achieve it using VariableSizedGridView and I did lazy loading as well. But I could find that there is no virtualization because of which the memory goes on increasing on scrolling down. Can you suggest me the how to achieve variable sized grid with virtualization like the pinterest app?
Please check the code below:
<local:VariableSizedGridView x:Name="samples"
ItemsSource="{Binding listofData}"
Margin="0,0,-24,0">
<local:VariableSizedGridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid ItemHeight="190"
ItemWidth="{Binding Converter={StaticResource ScreenWidthMultiplier}, ConverterParameter=1}"
Orientation="Horizontal"/>
</ItemsPanelTemplate>
</local:VariableSizedGridView.ItemsPanel>
<local:VariableSizedGridView.ItemTemplate>
<DataTemplate>
<Grid>
<local:MainPageTemplateSelector Content="{Binding}">
<local:MainPageTemplateSelector.BigTemplate>
<DataTemplate>
<Grid Height="380" Background="White"
Margin="0,3,6,3">
<Grid Margin="12" Background="Pink">
<Grid.RowDefinitions>
<RowDefinition Height="250"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Image Source="{Binding ImagePath}"
Stretch="Fill"/>
<Grid Grid.Row="1" Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}" Foreground="Red"
Margin="12 3 12 5"/>
</Grid>
</Grid>
</Grid>
</DataTemplate>
</local:MainPageTemplateSelector.BigTemplate>
<local:MainPageTemplateSelector.SmallTemplate>
<DataTemplate>
<Grid Height="190" Width="{Binding Converter={StaticResource ScreenWidthMultiplier}, ConverterParameter=1}"
Background="Blue" Margin="0,3,6,3">
<Grid Margin="12" Background="Green">
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition />
</Grid.RowDefinitions>
<Image Height="150"
Stretch="Fill"
Source="{Binding ImagePath}"/>
<Grid Grid.Row="1" Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<TextBlock Foreground="Red"
Text="{Binding Name}"
TextWrapping="Wrap"
Margin="12 5 12 5"/>
</Grid>
</Grid>
</Grid>
</DataTemplate>
</local:MainPageTemplateSelector.SmallTemplate>
</local:MainPageTemplateSelector>
</Grid>
</DataTemplate>
</local:VariableSizedGridView.ItemTemplate>
</local:VariableSizedGridView>
And the VariableSizedGridView
public class VariableSizedGridView : GridView
{
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
dynamic model = item;
try
{
element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.ColumnSpanProperty, model.ColSpan);
element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.RowSpanProperty, model.RowSpan);
}
catch
{
element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.ColumnSpanProperty, 1);
element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.RowSpanProperty, 1);
}
finally
{
element.SetValue(VerticalContentAlignmentProperty, VerticalAlignment.Stretch);
element.SetValue(HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch);
base.PrepareContainerForItemOverride(element, item);
}
}
Thank you,
Neenu

Related

UWP: Cannot make ListView scrollable

I have a page with a simple grid (2x2). In one grid on the bottom left corner is another Grid and inside this grid is a ListView bound to a collection. Entries can be added to the collection so the ListView grows in height (height of ListView is set to auto, so that all space available is used).
What I want is, if all available space (from the screen height) is used, scrollbars for the ListView should appear and should be usable. Funny (unfunny) thing is: scrollbars do appear but I cannot use them, I cannot scroll the ListView with the vertical scrollbar that appears when I hover the ListView.
It works, when I set the height of the ListView to a fixed value, but I don't want it that way, because then it doesn't use all the available space on the screen.
This is the XAML of the page (I removed some parts for demonstration purposes) :
<Page
x:Class="Qooli.TimeTracker.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Qooli.TimeTracker"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
...
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Name="spAddEntry" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="30">
<TextBlock Text="Add new entry:" Name="lblAddNewEntry" />
...
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="30">
<TextBlock Text="Allocated time:" Name="lblAllocatedTime" />
...
</StackPanel>
<Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="1" Margin="30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="Daily overview:" Name="lblDailyOverview" Grid.Row="0" Grid.Column="0" />
<ListView Name="lvTimeEntries" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left"
Height="Auto"
MinHeight="100"
VerticalAlignment="Top"
MinWidth="300"
SelectionMode="Single"
ItemsSource="{x:Bind ViewModel.TimeEntriesAdvancedCollectionView, Mode=OneWay}"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.IsVerticalRailEnabled="True"
ScrollViewer.VerticalScrollMode="Enabled">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="local:TimeEntry">
<Grid Background="{Binding Type, Converter={StaticResource TimeEntryTypeColorConverter}}" Padding="5">
<Grid.RowDefinitions>
<RowDefinition Height="200"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{x:Bind Time, Mode=OneWay}" Style="{StaticResource TitleTextBlockStyle}"
MinWidth="60"
MaxWidth="60"
Grid.Row="0" Grid.Column="0">
</TextBlock>
<TextBlock Text="{x:Bind Title, Mode=OneWay}" Style="{StaticResource BodyTextBlockStyle}" Margin="5,0,0,0"
MinWidth="100"
MaxWidth="100"
Grid.Row="0" Grid.Column="1">
</TextBlock>
<Button Name="btnEditTimeEntry" Grid.Row="0" Grid.Column="2" Margin="5,5,5,5">
<SymbolIcon x:Name="edit" Symbol="Edit"/>
</Button>
<Button Name="btnDeleteTimeEntry" Grid.Row="0" Grid.Column="3" Margin="5,5,5,5">
<SymbolIcon x:Name="delete" Symbol="Delete"/>
</Button>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListView>
</Grid>
<StackPanel Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="30">
<TextBlock Style="{StaticResource summaryTextStyle}" Text="Start time:" Name="lblDayStartTime" />
...
</StackPanel>
</Grid>
</Page>
Can someone spot why it is behaving this way?
You need to set the height of the second row to "*" for both grids.

change scrollbar inside scrollviewer

there is a grid inside scrollviewer which is having a vertical scrollbar. But that scroll bar is not clear, there are 2 small horizontal lines at the bottom of scrollbar.
<ScrollViewer VerticalScrollBarVisibility="Auto" >
<Grid VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Name="DetailsBackButton" Style="{StaticResource BackButtonStyle}" Click="AttachementDetailsBackButton_Click" Grid.Row="0" Visibility="Collapsed" />
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ListBox x:Name="DetailsListbox" BorderBrush="#d2d4d5" BorderThickness="1" FontFamily="Arial" FontSize="12px" ItemsSource="{Binding}" Grid.Row="0" Visibility="Collapsed" Width="{Binding RelativeSource={RelativeSource TemplatedParent},Path=ActualHeight}" Style="{DynamicResource ListBoxDefaultStyle}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid >
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Title}" Grid.Row="0" Style="{DynamicResource AttachmentTitleText}" MouseLeftButtonDown="AttachmentTitle_MouseLeftButtonDown" >
</TextBlock>
<Border Style="{DynamicResource AreaButtonBorder}" Grid.Row="1"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
<WebBrowser Name="WebBrowser" Style="{DynamicResource WebBrowserStyle}" Visibility="Visible" Grid.Row="1" Navigating="FullTextWebBrowser_Navigating" LoadCompleted="WebBrowser_LoadCompleted" />
</Grid>
</Grid>
</ScrollViewer>
And further, if I am scrolling it a bit, these 2 horizontal lines will go off. how this can be solved? or Is there any way to move the scroll bar little down by default inside scrollviewer?
Thanks.

WPF. MVVM. Add child to grid contained in dataTemplate

I want to use a dataTemplate to show a video source from four different cameras. My datatemplate is something like this:
<DataTemplate x:Key="MultiViewTemplate">
<Grid x:Name="MultiViewGrid" ShowGridLines="True" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid x:Name="GridVideo1" Grid.Column="0" Grid.Row="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Image x:Name="imageMultiVideoStreaming1" Margin="1" Source="/app;component/Images/No_image_available.png" />
</Grid>
<Grid x:Name="GridVideo2" Grid.Column="1" Grid.Row="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Image x:Name="imageMultiVideoStreaming2" Margin="1" Source="/app;component/Images/No_image_available.png" />
</Grid>
<Grid x:Name="GridVideo3" Grid.Column="0" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Image x:Name="imageMultiVideoStreaming3" Margin="1" Source="/app;component/Images/No_image_available.png" />
</Grid>
<Grid x:Name="GridVideo4" Grid.Column="1" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Image x:Name="imageMultiVideoStreaming4" Margin="1" Source="/app;component/Images/No_image_available.png" />
</Grid>
</Grid>
</DataTemplate>
...
<Grid x:name"MainGrid" >
<ContentControl x:Name="CameraContainer" Content="{Binding}" ContentTemplate=Value="{StaticResource MultiViewTemplate}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
</Grid>
At the beginning, when I run the application, every grid should show the image No_image_avaiable.png. It works correcty. After that, I try to connect with the cameras and each video source should be shown in GridVideo1, GridVideo2...
If I do this in code-behind I can see the video from camera 1...
MainGrid.Children.Add(VideoStreamingGrid1)
but I would like to do something like this:
...GridVideo1.Children.Add(VideoStreamingGrid1)
...GridVideo2.Children.Add(VideoStreamingGrid2)
...GridVideo3.Children.Add(VideoStreamingGrid3)
...GridVideo4.Children.Add(VideoStreamingGrid4)
How can I do that?
Thanks.

wpf is it possible to have a resizable horizontal expander?

I'm new to WPF. I was able to found out how to do a resizable vertical expander from here: Combine expander and grid (resizable expander)
So I thought making a horizontal would be easy, I have tried different ways with no success.
Can it be done without complex code? To have a glidsplitter between 2 grid rows which one of them has an expander
The layout looks like this:
Left expander/gridsplitter works fine. But the expander/gridsplitter at the bottom does not. It works fine without a gridsplitter though.
My XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="10" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<Expander ExpandDirection="Left" Header="">
<Expander.Content>
<Grid>
<!-- this works -->
</Grid>
</Expander.Content>
</Expander>
<TextBox AcceptsReturn="True" />
</DockPanel>
<GridSplitter Grid.Row="1" Height="10" HorizontalAlignment="Stretch" ResizeBehavior="PreviousAndCurrent" ResizeDirection="Rows"/>
<DockPanel Grid.Row="2">
<Expander ExpandDirection="Down" Header="Summary">
<Expander.Content>
<TextBox AcceptsReturn="True" />
</Expander.Content>
</Expander>
</DockPanel>
</Grid>
If you remove the middle row and the gridsplitter, it works fine but it's not resizable.
Any help is appreciated.
The 3rd rows height should also be proportional. Specify MinHeight for the first and bottom rows so that they don't completely shrink.
Edited XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="6*" MinHeight="100"/>
<RowDefinition Height="10" />
<RowDefinition Height="*" MinHeight="50"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<Expander ExpandDirection="Left" Header="">
<Expander.Content>
<Grid>
<!-- this works -->
</Grid>
</Expander.Content>
</Expander>
<TextBox AcceptsReturn="True" />
</DockPanel>
<GridSplitter Grid.Row="1" Height="2" HorizontalAlignment="Stretch"/>
<DockPanel Grid.Row="2">
<Expander ExpandDirection="Down" Header="Summary">
<Expander.Content>
<TextBox AcceptsReturn="True" />
</Expander.Content>
</Expander>
</DockPanel>
</Grid>
The following works for me. The GridSplitter is shown when expanded and hidden when collapsed.
I use ellipses that fill the panes in the example, because that makes it easy to see how much space is taken by each panel.
Xaml
<Grid Background="Green">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" Name="expanderRow"/>
</Grid.RowDefinitions>
<Ellipse Grid.Row="0" Fill="Black"></Ellipse>
<Expander Grid.Row="2" ExpandDirection="Up" IsExpanded="False" Background="Yellow"
Expanded="Expander_Expanded"
Collapsed="Expander_Collapsed">
<Ellipse Fill="Red"/>
</Expander>
<GridSplitter Grid.Row="1" Height="15" HorizontalAlignment="Stretch" Name="expander" Visibility="Collapsed"></GridSplitter>
</Grid>
Code behind
private GridLength expandedHeight = new GridLength(0.5, GridUnitType.Star);
public MainWindow()
{
InitializeComponent();
}
private void Expander_Expanded(object sender, RoutedEventArgs e)
{
expanderRow.Height = expandedHeight;
expander.Visibility = Visibility.Visible;
}
private void Expander_Collapsed(object sender, RoutedEventArgs e)
{
expandedHeight = expanderRow.Height;
expanderRow.Height = GridLength.Auto;
expander.Visibility = Visibility.Collapsed;
}

How to place two stack panels in grid vertically?

i am placing a grid like this in a grid of 1st column
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
<Image Source="{Binding PictureUrl}" Width="100" Height="100" Stretch="Fill" HorizontalAlignment="Left"></Image>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="1">
<HyperlinkButton Content="{Binding Path=GeoLocation}"/>
<TextBlock Text="{Binding Path=FormattedTimeStamp}"/>
</StackPanel>
</Grid>
The image is placing fine. But I cannot able to see the geo location. i think it takes only 100 width based on the image so it does not appears. But i want to place the image to left. and geo location below the image to right. Can any one please help me to find the solution.. this grid is the content of the data template just for more information.
As #coder is saying you should probably just change the code to:
<Grid Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinitionsHeight="*"/>
<ColumnDefinitionsHeight="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
...
</StackPanel>
<StackPanel HorizontalAlignment="Right" Grid.Column="1">
...
</StackPanel>

Categories