I have used listview inside scrollviewer in windows phone 8.1 rt app.
I have a requirement of scrolling to bottom of list but change view function is not working as per requirement.
Created a sample for same scenario:
MainPage.xaml
<Page
x:Class="InfiList.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:InfiList"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:customlv="using:InfiList"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<Style x:Key="ListViewStyle1" TargetType="ListView">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="TabNavigation" Value="Once"/>
<Setter Property="IsSwipeEnabled" Value="True"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="ItemContainerTransitions">
<Setter.Value>
<TransitionCollection>
<AddDeleteThemeTransition/>
<ReorderThemeTransition/>
</TransitionCollection>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<ItemsStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListView">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<ItemsPresenter FooterTransitions="{TemplateBinding FooterTransitions}" FooterTemplate="{TemplateBinding FooterTemplate}" Footer="{TemplateBinding Footer}" HeaderTemplate="{TemplateBinding HeaderTemplate}" Header="{TemplateBinding Header}" HeaderTransitions="{TemplateBinding HeaderTransitions}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid x:Name="root">
<ScrollViewer x:Name="MyScrollViewer" ViewChanged="OnViewChanged" IsVerticalScrollChainingEnabled="True">
<ListView x:Name="listview" ItemsSource="{Binding Collection}" Style="{StaticResource ListViewStyle1}" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel ItemsUpdatingScrollMode="KeepItemsInView"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Background="LightGray" HorizontalAlignment="Left" Margin="25">
<TextBlock Margin="25 25 25 50" FontSize="32" Text="{Binding}" TextWrapping="WrapWholeWords" MaxWidth="200"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollViewer>
</Grid>
<Page.BottomAppBar>
<CommandBar>
<AppBarButton Click="AppBarButton_Click">
</AppBarButton>
</CommandBar>
</Page.BottomAppBar>
MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=391641
namespace InfiList
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public ObservableCollection<String> Collection { get; set; }
private bool incall;
private int offset;
int _noofelements;
public MainPage()
{
this.InitializeComponent();
Collection = new ObservableCollection<string>();
listview.DataContext = this;
this.NavigationCacheMode = NavigationCacheMode.Required;
addNumber(0);
listview.Loaded += listview_Loaded;
}
void listview_Loaded(object sender, RoutedEventArgs e)
{
MyScrollViewer.ChangeView(null, int.MaxValue, null, true);
}
private void OnViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
ScrollViewer view = (ScrollViewer)sender;
Debug.WriteLine("Vertica Pffset: " + view.VerticalOffset);
if ((view.VerticalOffset < 0.1 * view.ScrollableHeight) & !incall)
{
incall = true;
addNumber(++offset);
}
}
private void addNumber(int offset)
{
int scrollcount = 30;
int start = offset * scrollcount;
for (int i = start; i < start + scrollcount; i++)
{
string s= (_noofelements++).ToString() ;
if (i % 2 == 0)
s += "msdkd kmsdksdk kdsmkd skmcds ckdsmckds ckdsmcksd kcmdskcdsc kdmmcsckdsc" + Environment.NewLine + "sdjndsjnds"
+ "msdkd kmsdksdk kdsmkd skmcds ckdsmckds ckdsmcksd kcmdskcdsc kdmmcsckdsc" + Environment.NewLine + "sdjndsjnds"
+ "dssdsddsds";
Collection.Insert(0,s);
}
incall = false;
}
/// <summary>
/// Scrolls to bottom
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AppBarButton_Click(object sender, RoutedEventArgs e)
{
MyScrollViewer.ChangeView(null, int.MaxValue, null, true);
//MyScrollViewer.ScrollToVerticalOffset(int.MaxValue);
//For scrolling till top
//MyScrollViewer.ScrollToVerticalOffset(0);
}
}
}
Is there any way to achieve desired functionality?
Use scrollviewer's ExtentHeight
scrollViewer.ChangeView(null, scrollViewer.ExtentHeight, null);
sample: https://github.com/HimanshPal/ListViewVirtualizationTest
I had a similar problem when I used a scroll viewer with the change view. It just never truly reached the bottom. Just by surprise, I found a function that is called UpdateLayout(). I use this function before the change view function and it finally worked.
Try to use ListView.ScrollIntoView,
for example:
listView.ScrollIntoView(listView.Items.Last(), ScrollIntoViewAlignment.Leading);
Related
I want to use CanContentRenderOutsideBounds on ListView. I know we can use it on ScrollViewer and that works, but it doesn't work on ListView. I've tried this:
<ListView ScrollViewer.CanContentRenderOutsideBounds="True">
<ListViewItem>
<Textblock>Content</Textblock>
</ListViewItem>
<!--This will be a lot of items-->
</ListView>
So, can we use CanContentRenderOutsideBounds for ListView? If don't, what can I do?
When you use ListView, it uses the default style, as follows:
<Style TargetType="ListView">
………
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListView">
<Border BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}">
<ScrollViewer x:Name="ScrollViewer"
TabNavigation="{TemplateBinding TabNavigation}"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
…...>
<ItemsPresenter Header="{TemplateBinding Header}"
…… />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As you can see, ListView has the built-in ScrollViewer, so you could use Visual Tree to find this ScrollViewer, then set its CanContentRenderOutsideBounds property to true in the Loaded event of ListView. Please refer to the following code.
Xaml code:
<ListView Height="100" x:Name="myListView" Loaded="ListView_Loaded">
<ListViewItem>
<TextBlock Text="item1"/>
</ListViewItem>
<ListViewItem>
<TextBlock Text="item2"/>
</ListViewItem>
// a lot of items
</ListView>
Code behind:
private void ListView_Loaded(object sender, RoutedEventArgs e)
{
var sc = FindChild<ScrollViewer>(myListView);
sc.CanContentRenderOutsideBounds = true;
}
public T FindChild<T>(DependencyObject parent)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (child is T typedChild)
{
return typedChild;
}
var inner = FindChild<T>(child);
if (inner != null)
{
return inner;
}
}
return default;
}
I am struggling to create a binding from a View + ViewModel to a Custom ComboboxItem. I am not sure it should work, I already had implemented complex UserControls and had to deal with setting the DataContext properly to make it work with MVVM, but this specific scenario doesn't work at all.
What I am trying to do:
Create a user control based on a Combobox. It will have Combobox behavior but it is customized. The combobox collapsed will show only a button without the Path, and when expanded (showing the dropdown list of combobox items), it will show more buttons customized.
This UserControl must work with MVVM (which is not working right now). If i set the ComboboxItem's content on the View hard coded they show correctly, but if I try to do a binding with viewmodel, it fails:
System.Windows.Data Error: 40 : BindingExpression path error: 'MessageName' property not found on 'object' ''MultiButtonControl' (Name='')'. BindingExpression:Path=MessageName; DataItem='MultiButtonControl' (Name=''); target element is 'TestComboBoxItem' (Name=''); target property is 'Content' (type 'Object')
I created :
A usercontrol MultiButtonControl containing a grid and a combobox with a specific style and a List called Children in the code behind (dependency property). I create a binding from the combobox on xaml with the Children property.
A custom control TestComboBoxItem.cs which extends from ComboBoxItem. And I created on Generic.xaml a style for that type.
DataContext:
I set the DataContext of the UserControl "MultiButtonControl.xaml" on the parent element -> Grid element as:
<Grid DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">
Currently working:
Right now the layout works fine. I can use my UserControl in the View, add the Children too. But the problem is the binding. I believe the problem is the DataContext. Because when I try to bind a property from ComboboxItem (TestComboBoxItem custom control) it fails, and if I set it hardcoded it works.
Let me give you the code:
View.xaml
<Window x:Class="Test2Manager.message.ModalMessageInsert"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Test2Manager.message"
xmlns:controls="clr-namespace:CSIncludes.controls;assembly=CSIncludes"
xmlns:wpf="clr-namespace:CSIncludes.wpf;assembly=CSIncludes"
mc:Ignorable="d"
WindowStyle="None"
AllowsTransparency="True"
WindowStartupLocation="CenterOwner"
WindowState="Maximized"
Background="#33000000"
Title="ModelMessageInsert"
Name="ModalWindow">
<Window.Resources>
<ResourceDictionary Source="/CSIncludes;component/Themes/Generic.xaml"/>
</Window.Resources>
<Grid Width="600" Height="400" VerticalAlignment="Center" HorizontalAlignment="Center" Background="Gray">
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"></TextBlock>
<Grid Grid.Row="1" Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center">Name:</TextBlock>
<TextBox Grid.Row="0" Grid.Column="2" VerticalAlignment="Center" Text="{Binding MessageName, UpdateSourceTrigger=PropertyChanged}">
<TextBox.Effect>
<DropShadowEffect Color="Yellow" Direction="270" ShadowDepth="2" Opacity="1" BlurRadius="2"></DropShadowEffect>
</TextBox.Effect>
</TextBox>
<!--<controls:AudioControl Grid.Row="2" Grid.Column="2" RecordingMode="False" ReproduceAudioPath="C:\Fabio\Musicas\05 - On The Turning Away.mp3"></controls:AudioControl>-->
<controls:MultiButtonControl Grid.Row="2" Grid.Column="2" Width="170" ParentButtonText="{Binding MessageName}" ParentButtonImage="/CSIncludes;component/images/audio_play.png">
<controls:MultiButtonControl.Children>
<!--Command2="{Binding TestCommand}"-->
<wpf:TestComboBoxItem Content="{Binding MessageName}"></wpf:TestComboBoxItem>
<wpf:TestComboBoxItem Content="Fabio 2"></wpf:TestComboBoxItem>
<wpf:TestComboBoxItem>Fabio 3</wpf:TestComboBoxItem>
</controls:MultiButtonControl.Children>
</controls:MultiButtonControl>
<!--<ComboBox Style="{StaticResource CustomCombobox}">
<ComboBoxItem>Item1</ComboBoxItem>
<ComboBoxItem>Item2</ComboBoxItem>
<ComboBoxItem>Item3</ComboBoxItem>
<ComboBoxItem>Item4</ComboBoxItem>
<ComboBoxItem>Item5</ComboBoxItem>
</ComboBox>-->
</Grid>
<StackPanel Orientation="Horizontal" Grid.Row="2" HorizontalAlignment="Center" Margin="5">
<Button Width="65" Command="{Binding SaveCommand}" CommandParameter="{Binding ElementName=ModalWindow}">Save</Button>
<Button Width="65" Command="{Binding CancelCommand}" CommandParameter="{Binding ElementName=ModalWindow}" Margin="5,0,0,0">Cancel</Button>
</StackPanel>
</Grid>
View - code-behind setting DataContext to ViewModel
using Arbeit.wpf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace Test2Manager.message
{
/// <summary>
/// Interaction logic for ModelMessageInsert.xaml
/// </summary>
public partial class ModalMessageInsert : Window
{
ViewModelModalMessageInsert vm;
public ModalMessageInsert(Test2Entities Context, Action UpdateList)
{
InitializeComponent();
vm = new ViewModelModalMessageInsert(Context, UpdateList);
DataContext = vm;
}
}
}
ViewModel
using CSIncludes.wpf;
using Test2EF;
using Test2Manager.database;
using Test2Manager.manager;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
namespace Test2Manager.message
{
class ViewModelModalMessageInsert
{
private Test2Entities Context;
private MessageDAL MessageDAL;
private Action UpdateList;
private ModelMessage Model;
public ViewModelModalMessageInsert(Test2Entities Context, Action UpdateList)
{
this.Context = Context;
this.UpdateList = UpdateList;
MessageDAL = new MessageDAL(Context);
Model = new ModelMessage();
Model.ClientId = LoggedManager.ClientId;
MessageName = "Teste";
}
public string MessageName
{
get { return Model.Name; }
set
{
Model.Name = value;
}
}
}
}
MultiButtonControl.xaml
<UserControl x:Class="CSIncludes.controls.MultiButtonControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CSIncludes.controls"
xmlns:wpf="clr-namespace:CSIncludes.wpf"
mc:Ignorable="d"
d:DesignHeight="55" d:DesignWidth="300">
<UserControl.Resources>
<!--<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border
x:Name="Border"
CornerRadius="0"
Background="#FF3F3F3F"
BorderBrush="#FF97A0A5"
BorderThickness="1" />
</Grid>
</ControlTemplate>-->
<ControlTemplate x:Key="ComboBoxTextBox" TargetType="{x:Type TextBox}">
<Border x:Name="PART_ContentHost" Focusable="False" Background="{TemplateBinding Background}" />
</ControlTemplate>
<Style x:Key="CustomCombobox" TargetType="{x:Type ComboBox}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="MinWidth" Value="120"/>
<Setter Property="MinHeight" Value="30"/>
<Setter Property="Foreground" Value="White"/>
<!--<Setter Property="DataContext" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"></Setter>-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<!--Template="{StaticResource ComboBoxToggleButton}"-->
<ToggleButton
VerticalAlignment="Center"
Height="{Binding ParentButtonHeight}"
Name="ToggleButton"
Focusable="false"
IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press">
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Background" Value="#5F1E78"></Setter>
<Setter Property="BorderBrush" Value="#5F1E78"></Setter>
<Setter Property="BorderThickness" Value="1"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border BorderBrush="#FF97A0A5" BorderThickness="1" HorizontalAlignment="Center" Width="{TemplateBinding ActualWidth}">
<Grid Background="{TemplateBinding Background}" HorizontalAlignment="Center" Width="{TemplateBinding ActualWidth}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1" Margin="0,0,8,0" Foreground="White" Name="Text" Text="{Binding ParentButtonText}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Image Grid.Column="2" Name="Image" Width="16" Height="16" Source="{Binding ParentButtonImage}" />
</Grid>
<!--<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="16" />
</Grid.ColumnDefinitions>
<TextBlock Margin="10" Foreground="White" Grid.Column="0" Name="Text" Text="{Binding ParentButtonText}" HorizontalAlignment="Center" />
<Image Grid.Column="1" Name="Image" Source="{Binding ParentButtonImage}" />
</Grid>-->
</Border>
<!--<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Text" Property="Foreground" Value="White" />
</Trigger>
</ControlTemplate.Triggers>-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.Style>
</ToggleButton>
<!--<ToggleButton Content="aaa"
Name="ToggleButton"
Template="{StaticResource ComboBoxToggleButton}"
Grid.Column="2"
Focusable="false"
IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press">
</ToggleButton>-->
<TextBox x:Name="PART_EditableTextBox" Style="{x:Null}" Height="{Binding ParentButtonHeight}" Template="{StaticResource ComboBoxTextBox}" HorizontalAlignment="Left"
VerticalAlignment="Center" Focusable="True" Background="White" Foreground="Black" Visibility="Hidden" IsReadOnly="{TemplateBinding IsReadOnly}"/>
<Popup Name="Popup" Placement="Top" PlacementTarget="{Binding ElementName=PART_EditableTextBox}" IsOpen="{TemplateBinding IsDropDownOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Slide">
<Grid Name="DropDown" SnapsToDevicePixels="True" MinWidth="{TemplateBinding ActualWidth}" Width="{TemplateBinding ActualWidth}" MaxHeight="{TemplateBinding MaxDropDownHeight}" Height="{TemplateBinding ActualHeight}">
<Border x:Name="DropDownBorder" Background="White" BorderThickness="1" BorderBrush="#888888"/>
<ScrollViewer Margin="0,0,0,0" SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="false">
<Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#888888"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
<Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true">
<Setter TargetName="DropDownBorder" Property="CornerRadius" Value="0"/>
<Setter TargetName="DropDownBorder" Property="Margin" Value="0,0,0,0"/>
</Trigger>
<Trigger Property="IsEditable" Value="true">
<Setter Property="IsTabStop" Value="false"/>
<Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
<!--<Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>-->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">
<ComboBox Style="{StaticResource CustomCombobox}" Focusable="False" x:Name="ComboBox" ItemsSource="{Binding Children}">
</ComboBox>
</Grid>
MultiButtonControl.xaml.cs
using CSIncludes.wpf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CSIncludes.controls
{
/// <summary>
/// Interaction logic for MultiButtonControl.xaml
/// </summary>
public partial class MultiButtonControl : UserControl
{
public MultiButtonControl()
{
InitializeComponent();
this.Loaded += UserControl_Loaded;
Children = new List<TestComboBoxItem>();
}
public static readonly DependencyProperty ParentButtonTextProperty = DependencyProperty.Register(
"ParentButtonText",
typeof(string),
typeof(MultiButtonControl));
public static readonly DependencyProperty ParentButtonImageProperty = DependencyProperty.Register(
"ParentButtonImage",
typeof(ImageSource),
typeof(AudioControl),
new UIPropertyMetadata(null));
public static readonly DependencyProperty ParentButtonHeightProperty = DependencyProperty.Register(
"ParentButtonHeight",
typeof(double),
typeof(MultiButtonControl));
public static readonly DependencyProperty ChildButtonHeightProperty = DependencyProperty.Register(
"ChildButtonHeight",
typeof(double),
typeof(MultiButtonControl));
public static readonly DependencyProperty ChildrenProperty = DependencyProperty.Register(
"Children",
typeof(List<TestComboBoxItem>),
typeof(MultiButtonControl));
public string ParentButtonText
{
get { return (string)GetValue(ParentButtonTextProperty); }
set { SetValue(ParentButtonTextProperty, value); }
}
public ImageSource ParentButtonImage
{
get { return (ImageSource)GetValue(ParentButtonImageProperty); }
set { SetValue(ParentButtonImageProperty, value); }
}
public double ParentButtonHeight
{
get { return (double)GetValue(ParentButtonHeightProperty); }
set { SetValue(ParentButtonHeightProperty, value); }
}
public double ChildButtonHeight
{
get { return (double)GetValue(ChildButtonHeightProperty); }
set { SetValue(ChildButtonHeightProperty, value); }
}
public List<TestComboBoxItem> Children
{
get { return (List<TestComboBoxItem>)GetValue(ChildrenProperty); }
set { SetValue(ChildrenProperty, value); }
}
void UserControl_Loaded(object sender, RoutedEventArgs e)
{
if (ParentButtonHeight == 0)
ParentButtonHeight = 35;
if (ChildButtonHeight == 0)
ChildButtonHeight = 25;
ComboBox.MaxDropDownHeight = ComboBox.Items.Count * ChildButtonHeight;
}
}
}
Generic.xaml
<Style x:Key="{x:Type wpf:TestComboBoxItem}" TargetType="{x:Type wpf:TestComboBoxItem}">
<Setter Property="ComboBoxItem.SnapsToDevicePixels" Value="true"/>
<Setter Property="ComboBoxItem.Foreground" Value="Black"/>
<Setter Property="ComboBoxItem.OverridesDefaultStyle" Value="true"/>
<Setter Property="ComboBoxItem.Height" Value="{Binding ChildButtonHeight}"/>
<Setter Property="ComboBoxItem.VerticalAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TestComboBoxItem}">
<Border Name="Border" Padding="5" SnapsToDevicePixels="true">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="true">
<Setter TargetName="Border" Property="Background" Value="#7E59F2"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#888888"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
TestComboBoxItem.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace CSIncludes.wpf
{
public class TestComboBoxItem : ComboBoxItem
{
static TestComboBoxItem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TestComboBoxItem), new FrameworkPropertyMetadata(typeof(ComboBoxItem)));
}
public static DependencyProperty CommandParameter2Property =
DependencyProperty.Register("CommandParameter2", typeof(object), typeof(TestComboBoxItem));
public static DependencyProperty Command2Property =
DependencyProperty.Register("Command2", typeof(ICommand), typeof(TestComboBoxItem));
public static DependencyProperty ItemTextProperty =
DependencyProperty.Register("ItemText", typeof(string), typeof(TestComboBoxItem));
public ICommand Command2
{
get { return (ICommand)GetValue(Command2Property); }
set { SetValue(Command2Property, value); }
}
public object CommandParameter2
{
get { return GetValue(CommandParameter2Property); }
set { SetValue(CommandParameter2Property, value); }
}
public string ItemText
{
get { return (string)GetValue(ItemTextProperty); }
set { SetValue(ItemTextProperty, value); }
}
}
}
Do you have any clue on how to fix that TestComboBoxItem bindings ? How would you do to make it work? After binding the Content, I will need to create bindings with ICommand too.
I'm pretty new to UWP Xaml C++/CX development so I apologize if I use the wrong terms.
I'm trying to make an image/photo thumbnail selection tray. The user is to select which folder to browse and the contents are displayed in the scrollable thumbnail tray with the filename displayed below.
Pages are built in xaml and i'm using C++/CX. The thumbnail tray is built using the following xaml
<ScrollViewer Grid.Row="1" Margin="20,20,20,20" ScrollViewer.VerticalScrollBarVisibility="Hidden">
<Grid x:Name="thumb_grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
</Grid.RowDefinitions>
</Grid>
</ScrollViewer>
I dynamically add new rows via code using
AddRow() {
RowDefinition^ rd = ref new RowDefinition();
rd->Height.Auto;
thumb_grid->RowDefinitions->Append(rd);
}
Then I populate each grid element with a new Button using
AddImageButton(int row, int col) {
Button^ b = ref new Button();
auto style = R->Lookup("ButtonStyle1");
b->Style = safe_cast<Windows::UI::Xaml::Style^>(style);
thumb_grid->Children->Append(b);
thumb_grid->SetRow(b, row);
thumb_grid->SetColumn(b, col);
}
Where "ButtonStyle1" is defined in my dictionary.xaml as
<Style x:Key="ButtonStyle1" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundTransparentBrush}"/>
<Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}"/>
<Setter Property="Padding" Value="8,4,8,4"/>
<Setter Property="Margin" Value="10"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="UseSystemFocusVisuals" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<!--REMOVED THIS SECTION TO REDUCE EXAMPLE CODE-->
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}"
Content="{TemplateBinding Content}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
<Image x:Name="thumb_image" Grid.Row="0" HorizontalAlignment="Stretch" Source="Assets/demo.jpg"/>
<TextBlock x:Name="thumb_filename" Grid.Row="1" Text="demo.jpg" FontSize="20" Foreground="White"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
TextAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
All this results in creating the desired output as shown in the following image. Obviously I'm just using a hardcoded image and text for the Button content at the moment.
The Problem
The question is how do I dynamically change the content of the custom image buttons?
Currently I can change the images within a button by accessing the content by name. However this requires the image content of a button have a unique name.
Xaml code
<Button x:Name="btnToggleShowHide" Grid.Row="1" Height="50" Width="50"
HorizontalAlignment="Left" VerticalAlignment="Bottom"
Background="Transparent"
Click="btnToggleShowHide_Click">
<Image x:Name="imgToggleShowHideBtn"
Source="Assets/Graphics/show.png"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
</Button>
and the C++/CX code for changing the image (excluding the actually logic, just showing the code used)
show = ref new BitmapImage(ref new Uri(imgToggleShowHideBtn->BaseUri->RawUri, "Assets/Graphics/show.png"));
hide = ref new BitmapImage(ref new Uri(imgToggleShowHideBtn->BaseUri->RawUri, "Assets/Graphics/hide.png"));
imgToggleShowHideBtn->Source = show;
imgToggleShowHideBtn->Source = hide;
But I cannot directly access the text within the custom button image "demo.jpg" by using its name
thumb_filename->Text = "test.jpg";
because the textblock thumb_filename only exists at runtime. In AddImageButton() I need to somehow set the content but can't figure out how to access the child objects in the button. In my mind I want to do something like
Button^ b = ref new Button();
auto style = R->Lookup("ButtonStyle1");
b->Style = safe_cast<Windows::UI::Xaml::Style^>(style);
//NOT ACTUAL CODE - THIS IS WHAT I'M TRYIN TO ACHIEVE
b->Image->Source = img; //obviously wont work because it has no knowledge whether ButtonStyle1 contains an image
b->TextBlock->Text = filename; //obviously wont work because it has no knowledge whether ButtonStyle1 contains a textblock
So I ended up using the approach suggested by Nico Zhu - MSFT and using GridView with data binding.
Firstly I created a button class (Note: I'm still in the process of refining so there may be some redundant snippets)
namespace Models {
[Windows::UI::Xaml::Data::Bindable]
public ref class FileBrowser sealed
{
private:
Platform::String^ _fname;
Platform::String^ _path;
ImageSource^ _thumbImage;
BitmapImage^ _imagedata;
public:
FileBrowser();
property Platform::String^ Filename
{
Platform::String^ get()
{
return _fname;
}
void set(Platform::String^ value)
{
_fname = value;
}
}
property Platform::String^ Filepath
{
Platform::String^ get()
{
return _path;
}
void set(Platform::String^ value)
{
_path = value;
}
}
property ImageSource^ ThumbImage
{
ImageSource^ get()
{
return _thumbImage;
}
void set(ImageSource^ value)
{
_thumbImage = value;
}
}
property BitmapImage^ ImageData
{
BitmapImage^ get()
{
return _imagedata;
}
void set(BitmapImage^ value)
{
_imagedata = value;
}
}
};
}
Add #include "FileBrowser.h" to the "MainPage.xaml.h". In my View.xaml page that contains the image browser/list add xmlns:local="using:Models" to the tag.
My GridView is created in the following way
<GridView x:Name="thumb_grid" Grid.Row="1" Margin="20,20,20,20" IsItemClickEnabled="True" SelectionMode="Single" ItemClick="thumb_grid_ItemClick">
<GridView.ItemTemplate>
<DataTemplate>
<Grid MaxHeight="200" MinHeight="200" MinWidth="200" MaxWidth="200">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="{Binding ImageData}"/>
<TextBlock Text="{Binding Filename}" Grid.Row="1" FontSize="20" Foreground="Gray" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.Items>
</GridView.Items>
</GridView>
At runtime a new button is added to the GridView using (where f and I supply the relevant file and image data)
auto btn = ref new Models::FileBrowser();
btn->Filename = f->GetAt(i)->DisplayName + f->GetAt(i)->FileType;
btn->Filepath = f->GetAt(i)->Path;
btn->ImageData = I;
thumb_grid->Items->Append(btn);
This now results in the desired image tray that displays the contents of a folder. Each image clickable/touchable and calls the same function, in this case each item in the GridView calls thumb_grid_ItemClick() when pressed.
Data from the button can be obtained using the following
void View::thumb_grid_ItemClick(Platform::Object^ sender, Windows::UI::Xaml::Controls::ItemClickEventArgs^ e)
{
auto btn = (Models::FileBrowser^)e->ClickedItem;
}
I'm building a Windows Store app with C#/XAML.
I have a simple ListView bound to an ItemsSource. There's a DataTemplate which defines the structure of each item and that has a ContentControl and a TextBlock in it.
I wish to change the Foreground colour of the TextBlock when the item is selected. Does anyone know how I can do this?
<ListView Grid.Column="1"
ItemsSource="{Binding Categories}"
ItemContainerStyle="{StaticResource CategoryListViewItemStyle}"
Background="{StaticResource DeepRedBrush}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ContentControl Content="{Binding Id, Converter={StaticResource Cat2Icon}}" HorizontalAlignment="Left" VerticalAlignment="Center" Width="110" Foreground="#FF29BCD6"/>
<TextBlock x:Name="catName" HorizontalAlignment="Left" Margin="0" TextWrapping="Wrap" Text="{Binding Name}" Grid.Column="1" VerticalAlignment="Center" FontSize="18.667"
Foreground="White"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
At the moment it's set to "White", so all I need is some binding expression that will change the Foreground property depending on the selected state of the item in the listview.
This does what you are asking for.
Using this XAML
<Grid x:Name="LayoutRoot" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView x:Name="MyListView" ItemsSource="{Binding Items}" SelectionMode="Single" SelectedItem="{Binding Selected, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Height="100" Width="300">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Ellipse x:Name="ellipse">
<Ellipse.Fill>
<SolidColorBrush Color="{Binding Color}" />
</Ellipse.Fill>
</Ellipse>
<TextBlock Grid.Column="1" VerticalAlignment="Center" Margin="10" Text="{Binding Title}" Style="{StaticResource HeaderTextBlockStyle}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
And this code behind:
public class MyModel : BindableBase
{
string _Title = default(string);
public string Title { get { return _Title; } set { SetProperty(ref _Title, value); } }
Color _Color = Colors.White;
public Color Color { get { return _Color; } set { SetProperty(ref _Color, value); } }
}
public class MyViewModel : BindableBase
{
public MyViewModel()
{
var items = Enumerable.Range(1, 10)
.Select(x => new MyModel { Title = "Title " + x.ToString() });
foreach (var item in items)
this.Items.Add(item);
}
MyModel _Selected = default(MyModel);
public MyModel Selected
{
get { return _Selected; }
set
{
if (this.Selected != null)
this.Selected.Color = Colors.White;
SetProperty(ref _Selected, value);
value.Color = Colors.Red;
}
}
ObservableCollection<MyModel> _Items = new ObservableCollection<MyModel>();
public ObservableCollection<MyModel> Items { get { return _Items; } }
}
public abstract class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void SetProperty<T>(ref T storage, T value, [System.Runtime.CompilerServices.CallerMemberName] String propertyName = null)
{
if (!object.Equals(storage, value))
{
storage = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
protected void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] String propertyName = null)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
It will update your data template for you.
I want to make this quick point: updating the content of your list through the ViewModel is the easiest and most light-weight approach. In this case, I am updating the color which is bound to the ellipse. However, if this were a complex set of changes, I might just set a style instead. Another option is to hide and show an entire set of controls in the template. You cannot, however, change the data template because it will not be re-rendered until the grid re-draws, and that's not what you want to do.
Just like changing the Ellipse color, you could change the TextBlock Foreground like you asked in your question. Either way, this gets you what you want in the most elegant way.
Best of luck!
You can simply handle the SelectionChanged event on the ListView and change the Foreground of the previously selected item and the newly selected item by either changing a view model value on SelectedItem that is bound to your Foreground.
You can also find the TextBlock using ListView.ItemContainerGenerator.ContainerFromItem(ListView.SelectedItem) + VisualTreeHelper as in Jerry Nixon's blog post and changing the Foreground directly, though that technique has a problem if your ListView is virtualized (which it is by default), since if you scroll away from the selected item and back - the item view with the changed Foreground might be recycled and used for another item in your collection.
Another option is to bind the Foreground to the IsSelected property of the parent ListViewItem which you can do in many ways as well. You could for example put your entire DataTemplate in a UserControl and bind the Foreground to the Parent of that control. The problem is I think Parent is not a dependency property and I see no ParentChanged event on FrameworkElement (base class for UserControl that defines the Parent property), so it might be tough to go this route. Another way to bind these is to define an attached dependency property or behavior that would set up that binding for you, but that is complicated (though I have already created one you could use here).
Finally you could modify your ListView.ItemContainerStyle and change the SelectedBackground value. If that works - it would be the ideal solution.
<Style TargetType="ListViewItem">
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="TabNavigation" Value="Local"/>
<Setter Property="IsHoldingEnabled" Value="True"/>
<Setter Property="Margin" Value="0,0,18,2"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ListViewItemPresenter CheckHintBrush="{ThemeResource ListViewItemCheckHintThemeBrush}" CheckBrush="{ThemeResource ListViewItemCheckThemeBrush}" ContentMargin="4" ContentTransitions="{TemplateBinding ContentTransitions}" CheckSelectingBrush="{ThemeResource ListViewItemCheckSelectingThemeBrush}" DragForeground="{ThemeResource ListViewItemDragForegroundThemeBrush}" DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}" DragBackground="{ThemeResource ListViewItemDragBackgroundThemeBrush}" DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}" FocusBorderBrush="{ThemeResource ListViewItemFocusBorderThemeBrush}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" PointerOverBackgroundMargin="1" PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" PointerOverBackground="{ThemeResource ListViewItemPointerOverBackgroundThemeBrush}" ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}" SelectedPointerOverBorderBrush="{ThemeResource ListViewItemSelectedPointerOverBorderThemeBrush}" SelectionCheckMarkVisualEnabled="True" SelectedForeground="{ThemeResource ListViewItemSelectedForegroundThemeBrush}" SelectedPointerOverBackground="{ThemeResource ListViewItemSelectedPointerOverBackgroundThemeBrush}" SelectedBorderThickness="{ThemeResource ListViewItemCompactSelectedBorderThemeThickness}" SelectedBackground="{ThemeResource ListViewItemSelectedBackgroundThemeBrush}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I've been struggeling with this a few days now and can't get it to work.
Maybe I'm not as good XAML programmer that I hoped I would be :)
Anyhow, my problem is that i want to bind a number of elements to a GridView and make them appear as squares without setting any width and height. The reason for this is that I want my GridView items to grow/shrink and expand to maximum size as the resolution or screen size vary.
Here is my XAML:
<UserControl.Resources>
<Style x:Key="MyItemContainerStyle" TargetType="ListViewItem">
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<!--<Setter Property="Height" Value="{Binding RelativeSource={RelativeSource Self}, Path=Width}" />-->
</Style>
<DataTemplate x:Key="MyItemTemplate">
<Border CornerRadius="4"
BorderBrush="Black"
BorderThickness="1"
Background="Blue">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">X</TextBlock>
</Border>
</DataTemplate>
<ItemsPanelTemplate x:Key="MyItemsPanelTemplate">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" />
</ItemsPanelTemplate>
</UserControl.Resources>
<Grid Background="White">
<GridView x:Name="MyGrid"
UseLayoutRounding="True"
ItemTemplate="{StaticResource MyItemTemplate}"
ItemsPanel="{StaticResource MyItemsPanelTemplate}"
ItemContainerStyle="{StaticResource MyItemContainerStyle}"
ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
</GridView>
</Grid>
And this is my code-behind:
public sealed partial class BlankPage : Page
{
public BlankPage()
{
this.InitializeComponent();
MyGrid.Items.Add(new ListViewItem { Content = 1 });
MyGrid.Items.Add(new ListViewItem { Content = 2 });
MyGrid.Items.Add(new ListViewItem { Content = 3 });
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
}
This however produces an output like this (rectangular items, not squares):
I would appreciate if someone who knows a bit more about XAML and WinRT (metro) development than I do, could explain this for me and maybe give me a working example.
Thanx!
EDIT
I got a tip to wrap my Border in a Viewbox as it seems to have some scaling/stretching abilities.
I played around a couple of hours but I can't really get it to work 100%.
This is my XAML now:
<UserControl.Resources>
<Style x:Key="MyItemContainerStyle" TargetType="ListViewItem">
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
<DataTemplate x:Key="MyItemTemplate">
<Viewbox>
<Border CornerRadius="3"
BorderBrush="Black"
BorderThickness="1">
<Grid Background="Blue" MinHeight="50" MinWidth="50">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">X</TextBlock>
</Grid>
</Border>
</Viewbox>
</DataTemplate>
<ItemsPanelTemplate x:Key="MyItemsPanelTemplate">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
</StackPanel>
</ItemsPanelTemplate>
</UserControl.Resources>
<Grid Background="White">
<GridView x:Name="MyGrid"
UseLayoutRounding="True"
ItemTemplate="{StaticResource MyItemTemplate}"
ItemsPanel="{StaticResource MyItemsPanelTemplate}"
ItemContainerStyle="{StaticResource MyItemContainerStyle}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled">
</GridView>
</Grid>
This produces this output:
Now it seems to stretch itself to a sqaure, but it sretches itself outside the screen. I also ran this example in several resoultions and screen sizes and it shows the same output, which means it scales correctly.
Help would be appreciated.
Thanx!
Your commented out binding is close to something that could sort of work - only you would need to bind to ActualWidth:
<Setter Property="Height" Value="{Binding ActualWidth, RelativeSource={RelativeSource Self}}" />
Overall I would suggest using hardcoded values - they make things easier on the CPU to layout, easier to deterministically design and will get scaled by Windows when screen size and resolution will require that. If you want more control over that - you can bind both Width and Height to the same value from a view model that you change depending on the need or write a converter that will convert a hardcoded Width/Height value to actual value depending on detected screen size/resolution or settings.