UWP images not displayed immediately on page - xaml

I am currently learning UWP and Xaml and have noticed that raised my interest.
When I make a page with a background image of 50kb that contains a grid with 7 other images of each respectively 500bytes, the page does get loaded but in the beginning the images are not yet displayed and will be shown a few seconds after (like 1-1.5second).
Is it possible in a way to tell the frame navigation or navigatedTo to wait opening the page untill all images have been loaded?
Or does do you need to preload the images at startup in a way?
-- Update --
I would like to avoid a progress dialog or such as the images will become essential part of the screen and showing a loading just for that is also a bit weird user experience as you first see a white background and then suddenly see the background appear with the images.
When I leave the 7 images out of the grid the background image is shown almost instant (in a few ms), but including them results all images being shown when all have been loaded leaving a flicker effect.
Furthermore it only happens on the first time they are loaded, when navigating away from the page and then back the images be shown instant afterwards.
Example:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Background>
<ImageBrush ImageSource="/Assets/Background/Scherm1.jpg"/>
</Page.Background>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Opacity="0" Source="ms-appx:///Assets/Image1.png"/>
<Image Grid.Column="1" Opacity="0" Source="ms-appx:///Assets/Image2.png"/>
<Image Grid.Column="2" Opacity="0" Source="ms-appx:///Assets/Image3.png"/>
<Image Grid.Column="3" Opacity="0" Source="ms-appx:///Assets/Image4.png"/>
<Image Grid.Column="4" Opacity="0" Source="ms-appx:///Assets/Image5.png"/>
<Image Grid.Column="5" Opacity="0" Source="ms-appx:///Assets/Image6.png"/>
<Image Grid.Column="6" Opacity="0" Source="ms-appx:///Assets/Image7.png"/>
</Grid>
</Page>

You could set an indeterminate ProgressBar where your image will be loaded. Something like this:
<BitmapImage ImageOpened="Banner_ImageOpened"/>
<ProgressBar x:Name="BannerProgressBar" IsIndeterminate="True"/>
And in your code behind:
private void Banner_ImageOpened(object sender, RoutedEventArgs e)
{
BannerProgressBar.Visibility = Visibility.Collapsed;
}

Related

Resposive Grid for Xamarin.Forms not resposive enough

I'm using a simple grid to make a menu list responsive for all resolutions. It's mainly working fine but if you see it on Android (and UWP if I resize the view to a small width) the right side has less space than the left size which has made it really ugly and unprofessional. Can you help me fix it?
This is the code:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
This is how it looks like:
In Xamarin.Forms, Grid takes Padding by itself so you should set Padding Accordingly OR if you don't want Padding than set Padding=0 .
process of illumination ?:
Could you also change the background colour of your ContentPage to make sure its not applying the margin.
most likely you have something like margin="2, 0, 0, 0" somewhere in your code
<StackLayout Padding="0" Margin="0">
<Grid Padding="0" Margin="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
</StackLayout>

Canvas causes contentcontrol children to spill out over control

I have the following XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="11" />
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<ListView ... Grid.Column="2"/>
<controls:GridSplitter
Grid.Column="1"
Width="11"
ResizeBehavior="BasedOnAlignment"
ResizeDirection="Auto"
Background="Gray"
Foreground="White"
FontSize="13">
<controls:GridSplitter.Element>
<Grid>
<TextBlock HorizontalAlignment="Center"
IsHitTestVisible="False"
VerticalAlignment="Center"
Text=""
Foreground="Black"
FontFamily="Segoe MDL2 Assets">
</TextBlock>
</Grid>
</controls:GridSplitter.Element>
</controls:GridSplitter>
<Canvas Canvas.ZIndex="1">
<ContentControl MaxWidth="750" Content="{Binding CAV, Mode=TwoWay}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" />
</Canvas>
</Grid>
Without the Canvas wrapped around the ContentControl in the first column, the children of the ContentControl properly stay within the content control and I can make it wider to see more of the children horizontally.
When I add the Canvas and set the ZIndex, the children of the content control spill out over the gridsplitter and the ListView without respecting the width of the contentcontrol.
The effect I'm trying to get it to allow expanding the width of the content control with the grid splitter and having that content control expand "over" the listview (instead of reducing the width of the listview).
What am I missing? I'm confused as to why the width of the contentcontrol isn't being respected suddenly just because I wrap it in a Canvas. Or should I not be using Canvas to get the "overlay" effect I want?
Canvas doesn't stretch its children. It only gives them the space they need. In fact, you don't have to wrap your ContentControl inside a Canvas to set the Canvas.ZIndex; it is an attached property that can be attached to the ContentControl directly. If you want a panel that allows its children/child to stretch, try a Border(single child only) or a Grid.
However, setting the ZIndex here seems to be unnecessary to me. Since the GridSplitter simply resizes the width of the columns, there won't be any overlay happening here.
If you want the overlay effect, you need to create another Grid with the same column layout and place your ListView there, something like the following -
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="11" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Grid x:Name="ListView" Background="LightGreen" Grid.Column="2" />
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="11" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<controls:GridSplitter Grid.Column="1" Background="LightBlue">
</controls:GridSplitter>
<Grid x:Name="ContentControl" Background="LightPink" Opacity="0.5" />
</Grid>
</Grid>
As an addendum Canvas tells the layout tree it uses no space. It doesn't care about the size of it's children, despite however many children it might have. For reference, here's the Canvas' MeasureOverride:
protected override Size MeasureOverride(Size constraint)
{
Size childConstraint = new Size(Double.PositiveInfinity, Double.PositiveInfinity);
foreach (UIElement child in InternalChildren)
{
if (child == null) { continue; }
child.Measure(childConstraint);
}
return new Size();
}
Which effectively says "I'm not taking up any space and my children can use whatever space they want".

Image flickers in ListView datatemplate

could someone tell me, how can I avoid image flickering in Datatemplate? Everytime I change the source through binding (MVVM pattern), the image in ListViewItem flickers. For other images in app I've used ImageOpened event in code-behind. But I can't be used when I have DataTemplate.
EDIT:
DataTemplate:
<DataTemplate x:Key="ContactItemDataTemplate" x:DataType="contactData:Contact">
<Grid MinHeight="48">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Column="0" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" x:Name="MainImage" Source="{x:Bind ImageStatusUri, Mode=OneWay}" Margin="0,8,12,8">
</Image>
<TextBlock Grid.Column="1" Text="{x:Bind Nickname, Mode=OneWay}" Foreground="Black" TextAlignment="Center"
VerticalAlignment="Center" FontSize="15" HorizontalAlignment="Left"/>
</Grid>
<Rectangle Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" StrokeThickness="0.4" Height="0.4"
VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Stroke="#D1D3D4"/>
</Grid>
</DataTemplate>
type Contact implements INotifyPropertyChanged.
EDIT2:
WriteableBitmap is working, but I have 3 images with scaling factors 100, 200 and 400. It always choose the image with scale 400. When I use normal binding no WriteableBitmap, it take image with scale 100.
The best solution here is for you to sub-class the Image control, overriding the Source property and controlling the transition from one image to another with a flicker-less flow. Learn here: https://mva.microsoft.com/en-US/training-courses/xaml-for-windows-10-controls-14482

Button fill inside grid column in Windows phone 8.1

I am new to Windows Phone development. I created a grid and added a button to one of the columns, the button does not fill the entire grid column. I am not even able to drag and resize the button control.
This is the code. The button appears at the center of column 0 and is cropped since it tries to fill into column2 as well. The same code seems to work fine in a 8.0 project I downloaded. Can anyone tell me how I can make the button fill the entire column and not spill into the second grid.
Updated code
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" Grid.Column="0">Text</Button>
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" Grid.Column="1">Text</Button>
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" Grid.Column="2">Text</Button>
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" Grid.Column="3">Text</Button>
</Grid>
Try adding this to your Button.
HorizontalAlignment="Stretch"
In WP8.1, its default value is Left.
Update
The cut-off issue is because there's a default MinWidth (109) set to the default Button style.
Try removing it by doing this.
MinWidth="0"

How do I prevent a column in Silverlight xaml Grid from taking up the entire row?

I want to display two columns in my Grid. The first is a textblock that is sometimes longer than the row meant to hold it. The second is a button. Is there a way to give the textblock as much room as possible while still leaving room for the button to go immediately after?
When I use the following code, the textblock will sometimes push the button outside the viewable area of the grid.
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Description}" HorizontalAlignment="Stretch" />
<Button Margin="4,0" Height="0" Width="16" Grid.Column="1" MinWidth="20" VerticalAlignment="Center" />
</Grid>
I've tried setting the first column definition Width="*", but then the button is always at the very end of the row, when I want it next to the text. Any suggestions?
This is in Silverlight 4.
Thanks.
EDIT
I want the grid to resize as the user changes the window size, so setting a hard limit on the grid size is no good. That being said, I was able to manually set the MaxWidth in the code behind when the TextBlock loads and when the window changes size. It's clunky, but it works.
Following will surely work..
<Grid x:Name="LayoutRoot" Background="White" Width="250">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="textBlock" Grid.Column="0" Text="Text Box" VerticalAlignment="Top"/>
<Button x:Name="button" Grid.Column="1" Content="Button" VerticalAlignment="Top" Width="60"/>
</Grid>
Add Following Line to xaml.cs file in constructor..
public MainPage()
{
InitializeComponent();
textBlock.MaxWidth = LayoutRoot.Width - button.Width;
}
Let me know if there is any issue with it.
Thanks..