C# UWP - The first image inside ListView is incorrectly sized - xaml

I have a simple layout that basically displays a list of items in ListView using an ItemsWrapGrid as the panel template. The problem I am having is that the first image in the ListView is always bigger than the rest, even with a fixed width / height set. I am completely stumped.
An image of the problem:
The ListView XAML is:
<ListView ItemsSource="{Binding Currencies}" ItemTemplate="{StaticResource PortfolioCurrencyTemplate}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal" Width="Auto" Height="Auto"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
The data template:
<Page.Resources>
<DataTemplate x:Key="PortfolioCurrencyTemplate" x:DataType="viewModels:PortfolioViewModel">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
BorderBrush="Black"
BorderThickness="1"
CornerRadius="2"
Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Grid.ColumnSpan="1" MaxWidth="100" MaxHeight="100" Source="https://www.cryptocompare.com/media/19633/btc.png"/>
<TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding Name}" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding Symbol}" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Grid.Row="2" Text="{Binding LastPrice}" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</Page.Resources>

Instead of using ListView and changing ItemsPanelTemplate to create a GridView Effect and tackle issues one by one, I would suggest you switch to AdaptiveGridView.
You can install Nuget Package for UWP Community Toolkit from Here
Add below namespace to your page
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
Now your ListView needs to be replaced like below.
<controls:AdaptiveGridView ItemsSource="{Binding Currencies}"
ItemTemplate="{StaticResource PortfolioCurrencyTemplate}"
DesiredWidth="250"/>
Output from Designer
Good Luck.

Related

SOLVED Pressing on ScrollViewer inside ListBox Item doesn't select the Item

I gave a ListBox that lists items. The items, can vary in size, but follow the same pattern:
picture................Metadata
ID
<ListBox Name="View" Grid.Row="2" ItemsSource="{Binding Human, ElementName=uc}"
SelectedItem="{Binding SelectedHuman, ElementName=uc}"
MouseDoubleClick="OnSubjectEditClick"
VerticalContentAlignment="Center"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.ScrollUnit="Pixel"
ScrollViewer.CanContentScroll="True"
Grid.IsSharedSizeScope="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate >
<DataTemplate >
<Border BorderBrush="#565656" BorderThickness="1" Margin="10" Padding="10">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="300" />
<RowDefinition MaxHeight="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" MinWidth="300" MaxWidth="500" SharedSizeGroup="col1"/>
<ColumnDefinition MaxWidth="500" Width="*" SharedSizeGroup="col2"/>
</Grid.ColumnDefinitions>
<Image Grid.Row="0" Grid.Column="0" MaxHeight="300" MaxWidth="300" Source="{Binding Thumb}"/>
<TextBlock Grid.Column="0" Grid.Row="1" Text="{Binding Name}" FontWeight="Bold" TextAlignment="Center"/>
<local:MetadataView Grid.Column="1" Grid.RowSpan="2" Metadata="{Binding Metadata}" HorizontalAlignment="Stretch" VerticalAlignment="Center" IsEdit="False" />
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The items inside Metadata .xaml looks like this. StackPanels containing actual Metadata are automatically generated by code inside "DisplayMode":
<Grid VerticalAlignment="Center" HorizontalAlignment="Stretch">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" CanContentScroll="False" Height="300" >
<StackPanel x:Name="DisplayMode" VerticalAlignment="Center" Grid.IsSharedSizeScope="True" >
...........
<StackPanel/> //AutoGenerated
............
</StackPanel>
</ScrollViewer>
</Grid>
The problem I'm facing is the fact, that I need to be able to select an item inside the ListBox. But, by adding ScrollViewer in Metadata.xaml it seems I Reroute the selector, so it is trying to select an item in Metadata ScrollViewer instead of ListBox when I press the part of the ListBox containing Metadata. If I press on Thumbnail, or even RightClick on any part of the ListBox - it seems to select just fine.
[SOLVED] After playing around with available options in ScrollViewer I stumbled across Focusable. Setting it to False did the trick.
I hope it will help someone in the future.
<Grid VerticalAlignment="Center" HorizontalAlignment="Stretch">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" CanContentScroll="False" Height="300" Focusable="False" >
<StackPanel x:Name="DisplayMode" VerticalAlignment="Center" Grid.IsSharedSizeScope="True" >
</StackPanel>
</ScrollViewer>
</Grid>

How to dynamically update ListView height while keeping the ScrollViewer enabled?

ListView is placed inside UserControl which is set in parent XAML to asterix "*" height.
I want to use ListView with possibility to scroll items, when there are items that exceed ListView. It should work for different size of window.
It works fine when I set Grid's RowDefinitions with fixed integer, but when I try to use asterix "*" ScrollViewer disables.
I also tried to bind and update RowDefinition's height via some code behind in overriden MeasureOverride method, but it didn't work as expected.
Here is code inside my UserControl:
<Grid x:Name="ContentArea"
Background="{StaticResource MixerBackground}">
<Grid.RowDefinitions>
<RowDefinition Height="{x:Bind ListViewHeight}" />
</Grid.RowDefinitions>
<ListView
ItemsSource="{x:Bind ViewModel.Source,Mode=TwoWay}"
CanDragItems="True"
CanReorderItems="True"
AllowDrop="True"
SelectionMode="Single"
ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Track">
<Grid
Background="LightGray"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
BorderBrush="Black">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<TextBlock
Text="{x:Bind Id}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="24"
Margin="20,5,20,5"/>
<Grid
Background="Black"
Width="500"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Grid.Column="1">
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I expect to get the ScrollViewer working correctly, but ListView stay at the old size or scroll bar is disabled - depending on Height value.
Is there any way to achieve dynamically resizing ListView with scroll?
Edit
Here is parent Page XAML code which is loaded into Frame via Light MVVM framework:
<Grid
x:Name="ContentArea">
<Grid
Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="*" />
<RowDefinition Height="300" />
</Grid.RowDefinitions>
<maineditor:MainEditorMenuControl x:Name="ProjectMenu" />
<maineditor:MainEditorWorkspaceControl x:Name="Workspace" Grid.Row="1"/>
<maineditor:MainEditorMixerControl x:Name="Mixer" Grid.Row="2" />
</Grid>
</Grid>
Edit 2
I think the problem may be connected with MVVM template I've created with Windows Template Studio plugin for Visual Studio. If I try to recreate minimal solution from scratch with all properties 1:1 as in my app it works in fresh project, but not in mine.
How to dynamically update ListView height while keeping the ScrollViewer enabled?
If you want make RowDefinition height same as the ListView, you could give the ListView a name and use {Binding ElementName=MyListView,Path=ActualHeight}syntax to bind both height property.
<Grid x:Name="ContentArea">
<Grid.RowDefinitions>
<RowDefinition Height="{Binding ElementName=MyListView,Path=ActualHeight}" />
</Grid.RowDefinitions>
<ListView
Name="MyListView"
CanDragItems="True"
CanReorderItems="True"
AllowDrop="True"
Loaded="MyListView_Loaded"
SelectionMode="Single"
ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListView.ItemTemplate>
<DataTemplate >
<Grid
Background="LightGray"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
BorderBrush="Black">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<TextBlock
Text="{Binding}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="24"
Margin="20,5,20,5"/>
<Grid
Background="Black"
Width="500"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Grid.Column="1">
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>

ListView is not Scrollable

I have the following ListView in my xaml layout:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<TextBlock Text="{StaticResource AppName}" Style="{StaticResource TitleTextBlockStyle}"/>
</StackPanel>
<StackPanel Grid.Row="1">
<ListView x:Name="lstStatus">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="12">
<Image Source="ms-appx:///Assets/Logo.png" Margin="12" Width="150" Height="150"></Image>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Path='Fullname'}" Style="{StaticResource ListViewItemSubheaderTextBlockStyle}"></TextBlock>
<TextBlock Text="{Binding Path='FormattedCreationTime'}" TextWrapping="WrapWholeWords"></TextBlock>
<TextBlock Text="{Binding Path='Text'}" Style="{StaticResource ListViewItemContentTextBlockStyle}" TextWrapping="WrapWholeWords" Margin="12"></TextBlock>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Grid>
However, I met two problems:
The list is not scrollable when it is longer than the screen.
The TextBlocks does not wrap at all although I already set TextWrapping.
I am pretty new to Windows Phone design. Please tell me where did I do wrong.
The StackPanel takes as much space as it needs. As the ListView grows, the StackPanel expands to allow it to grow, hence you cannot scroll to see the items you don't see on the screen.
Put the ListView in a Grid or limit the Height of the StackPanel.
<Grid Grid.Row="1">
<ListView x:Name="lstStatus">
...
Similar problem occurs in your ItemTemplate, and the fix is also similar.
<DataTemplate>
<Grid Margin="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image ...
<StackPanel Grid.Column="1">
<TextBlock ....
</StackPanel>
</Grid>
</DataTemplate>

ScrollViewer not working in windows phone with dynamic components

I have a stackpanel which sometimes contains more data than can fit on the screen. When this happens I'm unable to scroll down to see the rest of the list. So I added a ScrollViewer to fix this but I'm unable to get it working. This is the code:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ScrollViewer Height="500" Name="Scroller" VerticalScrollBarVisibility="Auto">
<StackPanel Orientation="Vertical" Name="Stack" Height="2000">
<TextBlock Text="{Binding BookableExplanation}" Foreground="#336699" TextWrapping="Wrap"/>
<Button Visibility="{Binding ShowLinkToSite, Converter={StaticResource BooleanToVisibilityConverter}}" cal:Message.Attach="[Event Click] = [Action OpenStuntOnWebAsRegularOffer]" Foreground="#FFFFFF" Background="#336699" BorderThickness="0">neckermann.be</Button>
<ListBox x:Name="DepartureDates" MinHeight="2000"
cal:Message.Attach="[Tap]=[Action OpenStuntOnWeb(DepartureDates.SelectedItem)]">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid DataContext="{Binding}" Background="#336699" Margin="0,10,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MinWidth="430"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Column="1" Orientation="Vertical" Margin="10,10,10,10">
<TextBlock Text="{Binding Date, StringFormat='dd/MM/yyyy'}" Foreground="#FFFFFF" TextWrapping="Wrap" TextAlignment="Center"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</ScrollViewer>
</Grid>
Any ideas ? On other views I just have text that scrolls fine, it's only when adding items dynamically that I ran into issues. Saw some posts here also about problems with the scrollviewer but followed those advice such as setting scrollviewer height lower than the stackpanel but didn't work. It's probably something really simple but can't find it :) It does the scrolling movement but just doesn't allow me to go down.
Thanks,
Jorn
I managed to fix it by reworking my XAML. It seems the stackpanel was the problem. Behavior is slightly different now but I can live with it.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="0,0,0,5">
<TextBlock Text="{Binding BookableExplanation}" Foreground="#336699" TextWrapping="Wrap"/>
<Button Visibility="{Binding ShowLinkToSite, Converter={StaticResource BooleanToVisibilityConverter}}" cal:Message.Attach="[Event Click] = [Action OpenStuntOnWebAsRegularOffer]" Foreground="#FFFFFF" Background="#336699" BorderThickness="0">neckermann.be</Button>
</StackPanel>
<ListBox Grid.Row="1" x:Name="DepartureDates"
cal:Message.Attach="[Tap]=[Action OpenStuntOnWeb(DepartureDates.SelectedItem)]">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid DataContext="{Binding}" Background="#336699" Margin="0,10,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MinWidth="430"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Column="1" Orientation="Vertical" Margin="10,10,10,10">
<TextBlock Text="{Binding Date, StringFormat='dd/MM/yyyy'}" Foreground="#FFFFFF" TextWrapping="Wrap" TextAlignment="Center"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
Listbox has inbuilt Scroll viewer. So if you manually add scroll viewer, both controls will fight each other.
Do remove your scroll viewer. Will work.

XAML element inside of ItemsControl DataTemplate sometimes has null parent (WinRT)

I'm making a win8 app. I have an ItemsControl with a DataTemplate. Inside this DataTemplate, there is a Grid. Inside this Grid there is a WebView and a ProgressRing. I have an event for LoadCompleted on the WebView, at which time I want to disable the ProgressRing. My thought was to use the following:
ProgressRing pr = ((sender as FrameworkElement).Parent as Grid).Children.First(t => t.GetType().Equals(typeof(ProgressRing))) as ProgressRing;
pr.IsActive = false;
And this works sometimes, but sometimes it claims that ((sender as FrameworkElement).Parent) is null. I verified from debugging that in these cases, the sender is still the correct WebView. The WebView is being shown on the screen and is formatted correctly - so how could its parent be null?
Here's the XAML:
<ItemsControl Margin="40,0,40,0" x:Name="resultsItemsControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="50,0">
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" MaxWidth="150"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="100" MaxWidth="100"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" x:Name="viewInBrowser" IsEnabled="False" Style="{StaticResource PreviewLinkAppBarButtonStyle}" Margin="0,0,40,0" Click="viewInBrowser_Click_1"></Button>
<TextBlock HorizontalAlignment="Left" TextAlignment="Left" Grid.Column="1" FontSize="30" Margin="0,20,0,20" FontWeight="Bold" FontFamily="Georgia" VerticalAlignment="Center" Text="{Binding Name}"></TextBlock>
<ProgressRing x:Name="loadingProgressRing" Margin="20,0" Grid.Column="2" Foreground="White" IsActive="True" HorizontalAlignment="Left" VerticalAlignment="Center"></ProgressRing>
<WebView ScriptNotify="WebView_ScriptNotify_1" Grid.Column="0" Grid.ColumnSpan="14" Grid.Row="1" Source="{Binding CurrentSearchUrl}" Width="0" LoadCompleted="WebView_LoadCompleted_1"></WebView>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I wouldn't use a WebView in an ItemsControl at all, but you could try putting your entire template in a UserControlm then you handle the event inside of the UserControl and don't need to care about sender, since you can just name the Grid and access a named Grid.