Changing width and height of Image inside a datatemplate - xaml

I have an image inside datatemplate. I want to change its height and width depending on certain conditions. How can I achieve that?
The XAML code I have:
<ListBox x:Name="options_stack" HorizontalAlignment="Left" Margin="198,569,0,33" Width="603" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollMode="Auto" Height="123" Style="{StaticResource ListBoxStyle}" ItemContainerStyle="{StaticResource ListBoxItemStyle}" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Image x:Name="options_image" Source ="{Binding}" Stretch="Fill" Width="123" Height="123" MaxHeight="123" MaxWidth="123" Tapped="apply_accessory"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Option 1
Since you are binding source property I would create a data structure (to use as DataContext) to hold Source, Width and Height properties and then bind them:
<Image x:Name="options_image"
Source ="{Binding Source}"
Width="{Binding Width}" Height="{Binding Height}"
MaxWidth="{Binding Width}" MaxHeight="{Binding Height}"
Stretch="Fill" Tapped="apply_accessory"/>
Option 2
Another option is to create different DataTemplates and a DataTemplateSelector to apply when certain conditions are met.
DataTemplateSelector ref: http://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector.aspx
Option 3
If you don't like both above options you have another way of doing it. In my last work (Taskin, if you want to take a look you can see the link in my profile) I needed to show different colors for different ListViewItems. I didn't want to create a new Property in my Task model to hold the color or a TemplateSelector just for this. So I created a simple IValueConverter instead that uses an already existent Priority object property and returns its color. Then I binded it like this:
<Border Background="{Binding Priority, Converter={StaticResource priorityToColorConverter}}"/>
XAML gives you many ways to implement what you want and it is up to you to choose the best and cleanest way to solve the problem you are facing.

Related

Apply Parallax effect into GridView

https://learn.microsoft.com/en-us/windows/uwp/design/motion/parallax
this is microsoft instruction to use the paralax they use the ListView to demo the effect
but my data is stored inside the Grid.View so can anyone show me how to implement into it ?
Microsoft said that we can use this with any element that contain the scrollviewer
ParallaxView works with GridView. The Source property of ParallaxView is for setting the element that either is or contains the ScrollViewer that controls the parallax operation. Here in your code snippet it bind the ForegroundElement to Source property but no such an element in. You need to name the GridView as ForegroundElement .
<GridView
x:Name="ForegroundElement"
IsItemClickEnabled="True"
ItemClick="Grid_Clicked"
ItemsSource="{x:Bind Icons}">
...
</GridView>
Besides this, the code snippet should work well. If you still cannot see the effects it may be caused by items count is not enough. ScrollViewer inside the GridView or ListView only be shown when the host control's layout space is being constrained smaller than the expanded content size, details please see ScrollViewer in a control template. You could try to add more items to check the effects.
Additionally, edit the question to add more details and avoid to put it as an answer.
<GridView Grid.Row="1" ItemsSource="{x:Bind Icons}" IsItemClickEnabled="True" ItemClick="Grid_Clicked">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Icon">
<StackPanel>
<Image Width="200" Height="200" HorizontalAlignment="Center" Source="{x:Bind ImageCover}"/>
<TextBlock FontSize="16" VerticalAlignment="Center" Text="{x:Bind Title}"/>
<TextBlock FontSize="10" VerticalAlignment="Center" Text="{x:Bind Room}"/>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
this is where the data stored
and this is the parallax
<ParallaxView Source="{x:Bind ForegroundElement}" VerticalShift="50">
<!-- Background element -->
<Image x:Name="BackgroundImage" Source="Assets/turntable.png"
Stretch="UniformToFill"/>
</ParallaxView>

GridView Items Width

Got a GridView that its items width are set by the first one width(Screenshot)
How could I set some auto width for each item?
<GridView ItemsSource="{x:Bind PopularItems}" Style="{StaticResource GVStyle}" Height="230">
<GridView.ItemTemplate>
<DataTemplate x:Name="GVTemp" x:DataType="models:LessDetails">
<StackPanel>
<Image Height="180" Width="132" Source="{x:Bind Img}" />
<TextBlock Margin="4,4,0,4" HorizontalAlignment="Stretch" TextAlignment="Center"
Text="{x:Bind Name}" Style="{ThemeResource BodyTextBlockStyle}" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
You can not auto-width each item in a GridView control, it is by designed to use the first item's size as the uniform size (ListViewItemPresenter for each items has the same size).
For the auto-size scenario, I suggest you using the StackPanel or creating a custom ItemsControl.
Use an ItemsStackPanel:
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
The only downside is that it doesn't wrap items.. For that you can use the ItemsWrapGrid but then you lose the auto-width functionality (first item determines the width of all items).
There's also the VariableSizedWrapGrid that can be used by giving items a certain ColumnSpan/RowSpan, but it's not quite the same as automatically calculating the width.
If you want the best of both world, probably you'll need to write your own custom panel.
UPDATE: For a solution that allows for both automatic width and item wrapping, you can use the WrapPanel control from the UWP Community Toolkit.

How to make Datatemplate derive size from each item separately?

I want to fill GridView with images. I have Datatemplate for sizing images to fit the GridView. But there is a problem with this template. Image itself is surrounded with Grid within the template. When app runs, this Grid has width derived from first item in the GridView. So when images have different aspect ratio, all following items has template with same sizes as first item. Do I overlook something simple or I need to create something like trigger?
Data template:
<DataTemplate x:Key="DataTemplatePhoto" >
<Grid Margin="0" ScrollViewer.VerticalScrollBarVisibility="Disabled" Height="{Binding Mode=OneWay, Source={StaticResource PhotoListHeight}}" HorizontalAlignment="Left">
<Image Source="{Binding FullURL}" Stretch="Uniform" ScrollViewer.VerticalScrollBarVisibility="Disabled" Margin="0"/>
</Grid>
</DataTemplate>
I think that you need TemplateSelector. Check out this so topic for samples.

Windows 8.1 how to automatically wrap grid items?

I'm building a universal app and my Win8.1 app has to show a grid of items. Normally the grid consists of 3 columns, but on smaller screens I want the items to wrap so that there are only 2 columns (or even 1). This is my code:
<GridView ItemsSource="{Binding Regions}" IsItemClickEnabled="True">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="3" MinWidth="400" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="10">
<Image Source="{Binding Code, Converter={StaticResource FlagIconConverter}, ConverterParameter='/Assets/Icons/Flags/{0}.png'}" Width="30" />
<TextBlock Text="{Binding NativeName}" Style="{StaticResource BodyTextBlockStyle}" Margin="10,0,0,10" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
Whenever I make the app smaller, the items do not automatically wrap. I tried solving this by changing the MaximumRowsOrColumns property with a VisualStateManager but that didn't work because it couldn't access my WrapGrid for some reason. Changing the property from code-behind didn't work either, because again it couldn't access the WrapGrid.
I tried this with both WrapGrid and ItemsWrapGrid (what is the difference anyway?) and ListView and GridView. No difference there.
Does anyone know how to accomplish this?
You shouldn't need to do anything. It should wrap based on the available client area. The only thing I can think of that would not make it wrap is that you put your <GridView> inside a fixed width container or a container that is size Auto in which you don't update the Observable Collection to notify the Grid to redraw/update itself.
For example this will not wrap.
<Grid Width="1000">
<GridView x:Name="myGridView" IsItemClickEnabled="True">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="5"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<!-- DATATEMPLATE -->
</GridView.ItemTemplate>
</GridView>
</Grid>
However get rid of that Width=1000 and it will wrap.
Example output 3 different sizes

How do I add text inside a shape in XAML

I am working on a Metro App using C++ and XAML. I want to create a polygon shape and add text inside it.
At first I thought of defining my own Controltemplate and apply it to Textblock but unfortunately it does not understand TargetType = "TextBlock".
Secondly, I thought of inheriting the Polygon class and see if I can do anything there but that class is sealed.
Any ideas on how to achieve this?
In WPF XAML you could do something simple like this:
<Grid Width="60" Height="100">
<Ellipse Fill="Yellow"/>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="Hello"/>
</Grid>
To get text in the centre of a yellow ellipse.
I'm guessing something that simple will work on WinRT.
You can use something like this with ContentControl or so many other controls:
<ContentControl Width="200" Height="100" Content="Something">
<ContentControl.Template>
<ControlTemplate>
<Grid>
<Ellipse Fill="Red"/>
<TextBlock Text="{Binding Content,RelativeSource={RelativeSource FindAncestor,AncestorType=ContentControl}}"
TextWrapping="Wrap"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Grid>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>