LongListSelector with cells of varying heights? - xaml

I'm looking to use the LongListSelector to display two columns of images, the catch is that the images are of various heights and a static known width.
An example of the layout would be:
+--------+ +--------+
| img1 | | img2 |
| | | |
+--------+ | |
+--------+ | |
| img3 | +--------+
| | +--------+
| | | img4 |
| | | |
+--------+ | |
+--------+
I found a project that shows a grid of images, called PhotoHubSample (from http://code.msdn.microsoft.com/wpapps/PhotoHub-Windows-Phone-8-fd7a1093), however this uses a consistent width and height - leading me to believe it's not possible to do what I want.
I can't see any other Windows Phone 8 examples, however if you want to see a real world example - the Pinterest app on the iPhone renders this kind of list... is there a way to do it in XAML? I'm not 100% set on using LongListSelector if there is an alternative.

I tried the VariableSizedWrapGrid and WrapPanel but both required known heights and widths (or proportions thereof). Since I knew my image width (half the screen width on the phone) I would be sizing the height of the image to ensure correct scaling. This meant the height was variable.
To achieve this, I created a ViewModel that had two image sources a 'LeftImage' and a 'RightImage' as well as a computed 'YOffset'. Now each Item in my LongListSelector would have the following XAML;
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0,0,17">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="14" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding LeftImageUri}" Margin="0,0,0,0" HorizontalAlignment="Left" Stretch="None"/>
<Canvas Grid.Column="2">
<Image Source="{Binding RightImageUri}" Stretch="None" Margin="{Binding YOffset, Converter={StaticResource ThicknessTopConverter}}"/>
</Canvas>
</Grid>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
I used an IValueConverter to create the Thickness object required for the vertical offset of the second image and wrapped this in a Canvas so that it could spill over the boundaries of the Grid.
To generate my ViewModel items I take the list of images and do a simple bin sorting algorithm between the Left and Right sides, making sure I always have an image in the left to match. I keep a running count of the offset and set appropriately on each item in the ViewModel collection.
It's a bit hacky as it's not pure XAML, and I'm sure I could turn it into a proper control, but this works fine for the one scrolling list I need. I also get all the benefits of the LongListSelector, I'll be implementing infinite scrolling eventually so all I need to keep track of in the ViewModel is the ongoing offset.
A view of what it looks like with 400px and 600px images is below (actual screenshot);

There is a variable sized wrap grid control available in the Kinnara wp toolkit... maybe it can help? You can get it at github here...

Related

Why CommandBarFlyout showing only eleven buttons maximum?

I need to create a CommandBarFlyout with many buttons.
My XAML code:
<StackPanel>
<Button Height="40" Width="40">
<Image Source="/Assets/StoreLogo.png"/>
<Button.Flyout>
<CommandBarFlyout>
<AppBarToggleButton>
<AppBarToggleButton.Icon>
<BitmapIcon UriSource="/Assets/StoreLogo.png"/>
</AppBarToggleButton.Icon>
</AppBarToggleButton>
</CommandBarFlyout>
</Button.Flyout>
</Button>
</StackPanel>
If I copy-paste twelve buttons in CommandBarFlyout - only first eleven are showing.
If I add more buttons - still first eleven shown.
From this document about Commandbarflyout, it mentions:
Unlike CommandBar, primary commands do not automatically overflow to
the secondary commands and might be truncated.
So the reason why only 11 buttons are displayed should be that the actual contents have overflowed the scope of the primary command and were truncated.
If you still want to continue to use CommandBarFlyout, you can also add commands to the SecondaryCommands collection. Or as the document said, to use CommandBar or Flyout.

Is it possible to make the background-colour of a Canvas field dependent on its value?

I want one datetime field's background colour to depend on its value. Like if a certain date is passed, the background changes to red.
Is there a way to make this in XAML?
I know there is no possibility of an "if" condition/instruction, but maybe you guys found some way to implement a similar function.
<Canvas Canvas.Left="893" Canvas.Top="208" Height="25" Width="99" Background="red" Panel.ZIndex="-1"/>
<assembly:FieldControl Canvas.Left="890" Canvas.Top="206" FieldControlType="DateControl" FormField="{x:Null}" Height="25" LabelColumnWidth="0" Refnr="123456789" ShowCaption="False" StateImageAlignment="Hidden" Width="106" FontSize="10" Foreground="DimGray"/>
this is my code so far. The Canvas-Part makes the Background go red.
I also tried to put the background property in the "FieldControl" but there it's useless.
EDIT:
After getting the information, that Data Binding could help me with this problem, i tested it like this:
<TextBox Canvas.Left="890" Canvas.Top="226" Name="Date" Width="99" Height="25" VerticalAlignment="Top" Text="{Binding ElementName=Date, Path = SelectedItem.Content, Mode = TwoWay, UpdateSourceTrigger = PropertyChanged}" Background="{Binding ElementName=Date, Path=SelectedItem.Content}">
But this is not the direction, i need. Do you have maybe any suggestion, how I can use Data binding to solve my problem?
Yes, it is possible. The concept you need to learn is XAML Data Binding.
You can implement the IValueConverter for this.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/converters
You can check the value on binding and return the background color.
how to give different text color for each item of listview in xamarin forms

Can someone explain to me the constraints, factor and constant in xamarin forms?

I have read the documentation on it but just can't understand it. I have this code
<RelativeLayout Padding="0" Margin="0" HorizontalOptions="FillAndExpand" HeightRequest="300" VerticalOptions="Start" BackgroundColor="Green">
<Image
Source="infoBox.png" x:Name="infobox" WidthRequest="400"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToView, Property=Height,Factor=1,Constant=0}"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToView, Property=X, Factor=0.10, Constant=25}"
/>
<Label Text=":)"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToView, Property=Y, Constant=5}"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToView, Property=X, Factor=0.10, Constant=25}"
TextColor="#000000"/>
</RelativeLayout>
I am trying to get some text to display on top of an image that takes up full width but not full height of a detail page in a master-detail navigation. I tried changing the constant/factor but I have no idea what it does and every time the result does not show what I expected. Can someone please explain what the constant and factor does? Like an example if I set factor to 1 for x constraint, what will it do? Make the width the original or make it fill the whole width?
Getting frustrated not understanding what it does exactly. Please help :(
Type is what you are positioning or sizing with repect to. It can be RelativeToParent or RelativeToView. If view use ElementName to say which view.
Property is what property you are trying to set on your control. You could be setting the Width or the Height or the X co-ordinate.
Factor is what percentage of the parent or view you want to use. If the parent is 500 pixels and Factor is 0.5 then you are setting a value of 250.
Constant allows you to alter the value you calculated using Factor. If you set Constant to -100 then the value we calculated previously would now be 150.
Having said all this, it would be much easier to position your image and label using a grid.
Put both the image and the label in the same grid row then position the label within the row using horizontal and vertical options. Use Margin to move the label up and down slightly.
Relative layout should be avoided it at all possible as it has a high computational cost according to the father of Xamarin forms Jason Smith.

Drawing arrow with XAML

I don't know how can I draw an arrow with XAML. I haven't any code at the moment.
Someone can help me to make this draw with XAML code ?
Thank you for your help.
You can use TextBlock (http://xahlee.info/comp/unicode_arrows.html)
<TextBlock Text="➔" />
Or Path (https://msdn.microsoft.com/en-us/library/system.windows.shapes.path%28v=vs.110%29.aspx)
<Path Stroke="Black" Data="M 10 0 L 16 4 L 10 8 M 0 4 L 16 4" />
Maybe this tool can be useful to you PathViewer
I just draw one through setting point by hand and adjust the point by eyes:
<Path Stretch="Fill" Fill="LimeGreen"
Data="M
0,115 95,115 //p1, p2 (when really use remove these comments)
65,90 85,90 //p3, p4
120,120 //p5
85,150 65,150 //p6, p7
95,125 0,125 //p8, p9
Z"
HorizontalAlignment="Center" Width="60" Height="60" />
You can adjust width/height, Basically p1,p2,p3,p4 and p6,p7,p8,p9 are symmetric, and Data can omit description and comma like this:
Data="M 0 115 95 115 65 90 85 90 120 120 85 150 65 150 95 125 0 125 Z"
The result:
Besides here's a way to Rotate the arrow, example below rotate another right arrow 180 degree, becoming a left arrow:
<Path Stretch="Fill" Fill="LimeGreen"
Data="M 0,110 70,110 45,90 75,90 120,120 75,150 45,150 70,130 0,130 Z"
HorizontalAlignment="Right" Width="30" Height="24" Margin="0,0,2,0"
RenderTransformOrigin=".5,.5">
<Path.RenderTransform>
<RotateTransform Angle="180" />
</Path.RenderTransform>
</Path>
There happens to be a nice third party library which is freely available and may fit some uses cases where arrows are needed as line ends.
The full code is too long to reproduce here, but I've linked to it below. I couldn't find any other repository of this code (e.g. Nuget, Github, etc.)
Article: Lines with Arrows, Charles Petzold, April 18, 2007, New York, N.Y.
Brief excerpt:
The Arrowheads.zip file contains a demo program and two classes
named ArrowLine and ArrowPolyline that derive from Shape ...
The ArrowLine class derives from ArrowLineBase and basically
duplicates the Line class by defining X1, Y1, X2, and Y2 properties;
ArrowPolyline duplicates the Polyline class by defining a Points
property.
...
Because the arrows are basically part of the line, they are affected
by all the properties that affect the line, such as Stroke,
StrokeThickness, StrokeStartLineCap, and StrokeLineJoin. If you set
IsArrowClosed to true, the Fill property comes into play; the
arrowhead will look most normal if Fill is set to the same brush as
Stroke.
The classes mentioned above are controls (written in C#) which can be used from XAML. Simple example:
xmlns:p="clr-namespace:Petzold.Media2D;assembly=Arrowheads"
...
<p:ArrowLine
X1="0"
Y1="0"
X2="148"
Y2="0"
Canvas.Top="18"
Canvas.Left="26"
/>
Example output:
(http://www.charlespetzold.com/blog/2007/04/Arrowheads.png)
Note that Charles very graciously provides this code to be reused, as stated in his FAQ:
All the code that I write and publish is free to use in your software
projects (whether personal or commercial) without restriction.
(the FAQ does mention some restrictions regarding publications so you should read it in full).
For a simple arrow, here's a trick using just a pair of lines. The first line is the main shaft of the arrow, the second is a zero-length line which forms the arrowhead. The shaft has no caps, and the arrowhead is purely a cap.
The whole arrow can be rotated by rotating the enclosing canvas, which I find useful.
<Canvas Width="75" Height="50">
<Line X1="0" Y1="25" X2="55" Y2="25" Stroke="#ffffff" StrokeThickness="20"/>
<Line X1="50" Y1="25" X2="50" Y2="25" Stroke="#ffffff" StrokeThickness="50" StrokeEndLineCap="Triangle"/>
</Canvas>

Wide columns pushing content off XAML Grid

I'd like to show a Grid with three columns, where each column fills the available space but not so that they push subsequent columns off the end of the grid. Each column needs to have at least some of its content (defined by MinWidth) visible.
This is what I'm after:
___________________________________________
| | | |
|very-wide-first-col...|second...|third...|
|______________________|_________|________|
This is what I get:
___________________________________________
| | |
|very-wide-first-column-text|second-column|-text|third-column-text
|___________________________|_____________|
Here's my code:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="very-wide-first-column-text" TextTrimming="CharacterEllipsis"/>
<TextBlock Grid.Column="1" Text="second-column-text" TextTrimming="CharacterEllipsis"/>
<TextBlock Grid.Column="2" Text="third-column-text" TextTrimming="CharacterEllipsis"/>
</Grid>
No combination of MinWidth and MaxWidth seems to achieve the desired layout - it seems they don't work with Auto and proportional sizing isn't what I want. I also tried using a DockPanel but that didn't help.
Use stars.
Width="2*" for the first column
Width="1*" for the other two.
This means that the total width available is divided evenly between the total of the numbers (in this example 4 - with the first column being 2/4 and the others each being 1/4 of the available width).
The total width is determined by whatever container the columns are in (the grid).