Windows phone 8.1 xaml Listview selected Item style - xaml

Dear all i am new to windows phone and xaml.
i have listview on my pivot template now i just want that when i select an item in the listview the backgroud color changed here is my xaml code
<ListView x:Name="LVPrimary" Grid.Row="2" Grid.Column="0"
ItemsSource="{Binding}"
IsItemClickEnabled="True"
ItemClick="LVPrimary_ItemClick"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Width="40" Height="40" CornerRadius="5,5,5,5">
<Border.Background>
<ImageBrush ImageSource="{Binding ImagePath}" />
</Border.Background>
</Border>
<StackPanel Grid.Row="0" Grid.Column="1" Margin="0,0,0,0">
<TextBlock
Text="{Binding Code}"
TextWrapping="Wrap"
Pivot.SlideInAnimationGroup="1"
CommonNavigationTransitionInfo.IsStaggerElement="True"
Style="{ThemeResource ListViewItemTextBlockStyle}"
Margin="0,0,19,0"/>
<TextBlock
TextWrapping="NoWrap" TextTrimming="CharacterEllipsis"
Text="{Binding Name}"
Pivot.SlideInAnimationGroup="2"
CommonNavigationTransitionInfo.IsStaggerElement="True"
Style="{ThemeResource ListViewItemContentTextBlockStyle}"
Margin="0,0,5,0"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Sorry for the late reply. You will have a List<ItemClass> and ObservableCollection<ItemClass>.
What you can do is - Define a SolidColorBrush Property and bind this property to your Item Grid. I have created this example : -
Here is my Item Class : - Make sure you Implement INotifyPropertyChanged.
public class Item : INotifyPropertyChanged
{
public string Something { get; set; }
public SolidColorBrush ItemBackground
{
get { return _itemBackground; }
set
{
_itemBackground = value;
OnPropertyChanged("ItemBackground");
}
}
private SolidColorBrush _itemBackground;
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
And My sample & simple Xaml is :-
<ListView x:Name="LVPrimary" IsItemClickEnabled="True" ItemClick="ListViewBase_OnItemClick">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Background="{Binding ItemBackground}" Height="100" Width="200">
<TextBlock Text="{Binding Something}"></TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And on Onlick Event I just changed the color of the clicked item like this :-
private void ListViewBase_OnItemClick(object sender, ItemClickEventArgs e)
{
((Item)e.ClickedItem).ItemBackground = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
}
Hope it will help you.

Below solution works fine for me..
var griditem = ListViewName.ContainerFromItem(ListViewName.SelectedItem);
var a = ((Windows.UI.Xaml.Controls.Panel)((Windows.UI.Xaml.Controls.ContentControl)listViewItem).ContentTemplateRoot
a.Background= new SolidColorBrush(Windows.UI.Colors.Red);
var textitem = ListViewName.ContainerFromItem(ListViewName.SelectedItem);
var a = ((Windows.UI.Xaml.Controls.Panel)((Windows.UI.Xaml.Controls.ContentControl)listViewItem).ContentTemplateRoot).Children;
((TextBlock)a.ElementAt(0)).Text= "Your Text";

Related

Refresh SemanticZoom ObservableCollection in ViewModel

When using a SemanticZoom control, is there a way to update the ObservableCollection in the ViewModel after a table change? After making changes to the table in SQLite, within the same page (categories.xaml.cs), the SemanticZoom control does not update. Reloading the page from menu navigation does reload the page with the correct data. If the control just took an ObservableCollection as it's items source, the ObservableCollection could just be refreshed. Using a ViewModel was the only code example I could find for the SemanticZoom control. Thanks in advance!
categories.xaml
<Page.DataContext>
<vm:CategoriesViewModel></vm:CategoriesViewModel>
</Page.DataContext>
<Page.Resources>
<CollectionViewSource x:Name="Collection" IsSourceGrouped="true" ItemsPath="Items" Source="{Binding CategoryGroups}" />
</Page.Resources>
<SemanticZoom Name="szCategories" ScrollViewer.ZoomMode="Enabled">
<SemanticZoom.ZoomedOutView>
<GridView ScrollViewer.IsHorizontalScrollChainingEnabled="False">
<GridView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Group.Name }" Foreground="Gray" Margin="5" FontSize="25" />
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
<ListView Name="lvCategories" ItemsSource="{Binding Source={StaticResource Collection}}" Tapped="lvCategories_Tapped">
<ListView.ItemTemplate>
<DataTemplate x:DataType="data:Category">
<StackPanel>
<TextBlock Text="{Binding Title}" Margin="5" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text='{Binding Name}' Foreground="Gray" FontSize="25" Margin="5,5,5,0" />
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</SemanticZoom.ZoomedInView>
</SemanticZoom>
categories.xaml.cs
public Categories()
{
this.InitializeComponent();
var collectionGroups = Collection.View.CollectionGroups;
((ListViewBase)this.szCategories.ZoomedOutView).ItemsSource = collectionGroups;
}
CategoriesViewModel.cs
internal class CategoriesViewModel : BindableBase
{
public CategoriesViewModel()
{
CategoryGroups = new ObservableCollection<CategoryDataGroup>(CategoryDataGenerator.GetGroupedData());
}
private ObservableCollection<CategoryDataGroup> _groups;
public ObservableCollection<CategoryDataGroup> CategoryGroups
{
get { return _groups; }
set { SetProperty(ref _groups, value); }
}
}
public abstract class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (object.Equals(storage, value)) return false;
storage = value;
this.OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged(string propertyName)
{
var eventHandler = this.PropertyChanged;
if (eventHandler != null)
{
eventHandler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
SymanticZoom.cs
internal class CategoryDataGroup
{
public string Name { get; set; }
public List<CategoryData> Items { get; set; }
}
internal class CategoryData
{
public CategoryData(string grp, string title)
{
Grp = grp;
Title = title;
}
public string Grp { get; private set; }
public string Title { get; private set; }
}
internal class CategoryDataGenerator
{
private static List<CategoryData> _data;
public static List<CategoryDataGroup> GetGroupedData()
{
if (_data != null)
_data.Clear();
GenerateData();
return _data.GroupBy(d => d.Grp[0],
(key, items) => new CategoryDataGroup() { Name = key.ToString(), Items = items.ToList() }).ToList();
}
private static void GenerateData()
{
ObservableCollection<Category> ocCategories = new ObservableCollection<Category>();
SQLiteManager.Categories.Select(ocCategories);
_data = new List<CategoryData>();
foreach (var temp in ocCategories)
{
_data.Add(new CategoryData(temp.Name.Substring(0,1), temp.Name));
}
}
}
The zoomed-in view and zoomed-out view should be synchronized, so if a user selects a group in the zoomed-out view, the details of that same group are shown in the zoomed-in view. You can use a CollectionViewSource or add code to synchronize the views.
For more info, see Semantic zoom.
We can use CollectionViewSource control in our page, it provides a data source that adds grouping and current-item support to collection classes. Then we can bind the GridView.ItemSource and ListView.ItemSource to the CollectionViewSource. When we set new data to the CollectionViewSource, the GridView in SemanticZoom.ZoomedOutView and ListView in SemanticZoom.ZoomedInView will be updated.
xmlns:wuxdata="using:Windows.UI.Xaml.Data">
<Page.Resources>
<CollectionViewSource x:Name="ContactsCVS" IsSourceGrouped="True" />
<DataTemplate x:Key="ZoomedInTemplate" x:DataType="data:Contact">
<StackPanel Margin="20,0,0,0">
<TextBlock Text="{x:Bind Name}" />
<TextBlock Text="{x:Bind Position}" TextWrapping="Wrap" HorizontalAlignment="Left" Width="300" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="ZoomedInGroupHeaderTemplate" x:DataType="data:GroupInfoList">
<TextBlock Text="{x:Bind Key}"/>
</DataTemplate>
<DataTemplate x:Key="ZoomedOutTemplate" x:DataType="wuxdata:ICollectionViewGroup">
<TextBlock Text="{x:Bind Group.(data:GroupInfoList.Key)}" TextWrapping="Wrap"/>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<SemanticZoom x:Name="Control1" Height="500">
<SemanticZoom.ZoomedInView>
<GridView ItemsSource="{x:Bind ContactsCVS.View,Mode=OneWay}" ScrollViewer.IsHorizontalScrollChainingEnabled="False" SelectionMode="None"
ItemTemplate="{StaticResource ZoomedInTemplate}">
<GridView.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource ZoomedInGroupHeaderTemplate}" />
</GridView.GroupStyle>
</GridView>
</SemanticZoom.ZoomedInView>
<SemanticZoom.ZoomedOutView>
<ListView ItemsSource="{x:Bind ContactsCVS.View.CollectionGroups}" SelectionMode="None" ItemTemplate="{StaticResource ZoomedOutTemplate}" />
</SemanticZoom.ZoomedOutView>
</SemanticZoom>
</StackPanel>
</Grid>

How to Bind IsSelected Property in DataTemplate of ListViewItem

Well, I want to make the ListViewItem in UWP ,that'll be changing his view on selecting. So I need to change the Visibility property of some elements of ListViewItem on selecting.
I found some way to do this with making custom Style of ListViewItem and Binding IsSelected property like this:
<Style x:Key="VehicleListViewItemStyle" TargetType="ListViewItem" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Grid Background="Gray" Margin="1">
<Border Margin="2" Padding="10" Background="Gray" >
<StackPanel>
<ContentPresenter x:Name="Presenter1" />
<StackPanel Orientation="Horizontal" Background="Transparent" Margin="-10,0,-9,-9" VerticalAlignment="Center" x:Name="infoPanel"
Visibility="{Binding IsSelected, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}">
<TextBlock Text="{Binding DeviceID}/> </StackPanel>
</StackPanel>
</Border>
<Border BorderThickness="1" BorderBrush="Orange" Visibility="{Binding IsSelected, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Its working good, but with this way I cant bind the DeviceID text.
Another one way is creating DataTemplate like this:
<DataTemplate x:Key="monitoringListViewItem" x:Name="item">
<Grid Background="Gray" Margin="1" Width="300" >
<StackPanel>
<ContentPresenter x:Name="Presenter"/>
<StackPanel Orientation="Horizontal">
<Image Source="/Assets/14th_crane_stop.png" Height="50" Width="50" Stretch="Uniform"/>
<StackPanel Orientation="Vertical" Margin="25,0,0,0 "
Visibility="{Binding IsSelected, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}"
>
<TextBlock Text="{Binding DeviceID}" Style="{StaticResource VehicleTextStyle}"/>
<TextBlock Text="{Binding Mark}" Style="{StaticResource VehicleTextStyle}"/>
</StackPanel>
</StackPanel>
</StackPanel >
</Grid>
</DataTemplate>
Now I can bind the text correctly, but cant bind the IsSelected property. I've tried to do this with different Modes, but it still doesn't work because I cant use the TemplatedParent key inside the DataTemplate.
So I need some answers:
-can I bind the text in first way and how can I do that?
-how can I bind the IsSelected property in the second way?
I don't recommend changing the ListViewItem template since you lose all the bells and whistles it provides (selection appearance, ability to be checked, etc).
Using Mode=TemplatedParent in the second snippet won't work because the templated parent from that context is a ListViewItemPresenter, not the ListViewItem (which is the presenter's parent).
It looks like what you're trying to do is to show additional information in the list item when it is selected.
Single selection
C# classes
public class NotifyPropertyChangedBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<T>(ref T property, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(property, value))
{
return false;
}
property = value;
OnPropertyChanged(propertyName);
return true;
}
}
public class Item : NotifyPropertyChangedBase
{
private string text;
public string Text
{
get { return text; }
set { SetProperty(ref text, value); }
}
private bool isSelected;
public bool IsSelected
{
get { return isSelected; }
set { SetProperty(ref isSelected, value); }
}
}
public class MainPageViewModel : NotifyPropertyChangedBase
{
public List<Item> Items { get; set; }
private Item selectedItem;
public Item SelectedItem
{
get { return selectedItem; }
set
{
if (selectedItem != value)
{
if (selectedItem != null)
{
selectedItem.IsSelected = false;
}
SetProperty(ref selectedItem, value);
if (selectedItem != null)
{
selectedItem.IsSelected = true;
}
}
}
}
public MainPageViewModel()
{
Items = new List<Item>()
{
new Item() { Text = "Apple" },
new Item() { Text = "Banana" },
};
}
}
MainPage.xaml
<ListView ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Item">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Text}"/>
<!-- x:Bind doesn't require visibility converter if min SDK is targeting Anniversary update -->
<TextBlock Text="I'm selected!" Grid.Column="1" Visibility="{x:Bind IsSelected, Mode=OneWay}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
MainPage.xaml.cs
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
DataContext = new MainPageViewModel();
}
}
Multiple selection
Same as single selection but with the following changes:
MainPageViewModel
public class MainPageViewModel : NotifyPropertyChangedBase
{
public List<Item> Items { get; set; }
public MainPageViewModel()
{
Items = new List<Item>()
{
new Item() { Text = "Apple" },
new Item() { Text = "Banana" },
};
}
public void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (Item item in e.RemovedItems)
{
item.IsSelected = false;
}
foreach (Item item in e.AddedItems)
{
item.IsSelected = true;
}
}
}
MainPage.xaml
<ListView ItemsSource="{Binding Items}" SelectionChanged="{x:Bind ViewModel.SelectionChanged}" SelectionMode="Extended">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Item">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Text}"/>
<TextBlock Text="I'm selected!" Grid.Column="1" Visibility="{x:Bind IsSelected, Mode=OneWay}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
MainPage.xaml.cs
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
DataContext = new MainPageViewModel();
}
public MainPageViewModel ViewModel => (MainPageViewModel)DataContext;
}
To answer the actual question in the topic: Yes you can bind ListViewItem.IsSelected quite easily. Make sure your DataTemplate content is wrapped in a ListViewItem.
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:MyItemViewModel">
<ListViewItem IsSelected="{Binding IsSelected, Mode=TwoWay}">
<Grid>
// template content
</Grid>
</ListViewItem>
</DataTemplate>
</ListView.ItemTemplate>
Note that there are numerous Q&As here for WPF saying this does not work. It does work with UWP (at least as of SDK 10.0.19041). The WPF answers suggest binding it in the ItemsPanelTemplate or in a ResourceDictionary. For some reason this does not work in UWP.
I did the following and it worked fine
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:PersonalProfile">
<ListViewItem x:Name="root">
<Grid >
<!-- .... -->
<CheckBox IsChecked="{Binding ElementName=root, Path=IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</ListViewItem>
</DataTemplate>
</ListView.ItemTemplate>

TwoWay Data Binding with MVVM Light on Windows Phone 8.1

I'm trying to create a custom Button with ListPickerFlyout using MVVM. The result that i wanna reach is something like that:
custom Button with ListPickerFlyout
My problem is how to bind the SelectedItem from ListPickerFlyout to the content TextBlock.
I'm using MVVM Light Windows Phone 8.1 (Store Appp).
My Xaml code:
<Button Background="White"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="40" />
</Grid.ColumnDefinitions>
<!-- Content TextBlock -->
<TextBlock Text="{Binding MyVM.SelectedItem, Mode=TwoWay}"
Style="{StaticResource DefaultTextBlock}"
FontSize="22"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="10, 0, 0, 0"/>
<Image Height="20" Grid.Column="1"
VerticalAlignment="Center" HorizontalAlignment="Center"
Source="../Assets/icons/arrow_down.png"/>
</Grid>
<Button.Flyout>
<ListPickerFlyout PickerFlyoutBase.Title="$Items$"
ItemsSource="{Binding MyVM.listItems}"
SelectedItem="{Binding MyVM.SelectedItem, Mode=TwoWay}" >
<ListPickerFlyout.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding}"
Style="{StaticResource DefaultTextBlock}"
FontSize="22"/>
</StackPanel>
</DataTemplate>
</ListPickerFlyout.ItemTemplate>
</ListPickerFlyout>
</Button.Flyout>
And in MyVM i have
public string SelectedItem { get; set; }
Edit:
Solved the problem, i forgot to add RaisePropertyChanged("SelectedItem");.
So, in my MVVM class:
private string _selectedItem;
public string SelectedItem
{
get { return _selectedItem; }
set
{
if (_selectedItem != value)
{
_selectedItem = value;
RaisePropertyChanged("SelectedItem");
}
}
}
Just need to add the RaisePropertyChanged("SelectedItem"); in MVVM class.
The complete code:
private string _selectedItem;
public string SelectedItem
{
get { return _selectedItem; }
set
{
if (_selectedItem != value)
{
_selectedItem = value;
RaisePropertyChanged("SelectedItem");
}
}
}

XAML Gridview to add an item directly

I successfully coded an XAML Gridview to show list of items.
However, I want to add an [+(ADD ITEM)] button at the end of the Gridview.
The ADD button has should have a custom template (at least a default button) which is different from the content item.
My XAML source is below:
<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemsGridView"
AutomationProperties.Name="Items"
TabIndex="1"
Grid.RowSpan="2"
Padding="116,136,116,46"
ItemsSource="{Binding Source={StaticResource DataSource}}"
SelectionMode="None"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick">
<GridView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}">
<StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
<TextBlock Text="{Binding Subject}" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource BaseTextBlockStyle}" Height="60" Margin="15,0,15,0" FontWeight="SemiBold"/>
<TextBlock Text="{Binding TargetDate}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource BaseTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10" FontSize="12"/>
</StackPanel>
</Border>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<!--
Something like that..
<Button Content="+" x:Name="btnAdd" />
-->
</GridView>
And, how can I add a ADD button(grid item) to XAML? thanks
You can achieve that by using a DataTemplateSelector, basically what you need to do is :
define another class that will represent the GridView "addItem"
public class GridItem
{
public String Subject { get; set; }
public String TargetDate { get; set; }
}
public class AddGridItem : GridItem
{
public bool IsGridItem { get; set; }
}
Make sure that your GridView's ItemSource collection has always an AddGridItem in it
private ObservableCollection<GridItem> _gridItems =new ObservableCollection<GridItem>()
{
new GridItem()
{
Subject = "Subject1",
TargetDate = "TargetDate"
},new GridItem()
{
Subject = "Subject2",
TargetDate = "TargetDate"
},new GridItem()
{
Subject = "Subject3",
TargetDate = "TargetDate"
},new AddGridItem()
{
IsGridItem = true
}
};
public ObservableCollection<GridItem> GridItems
{
get
{
return _gridItems;
}
set
{
if (_gridItems == value)
{
return;
}
_gridItems = value;
}
}
Create a DataTemplateSelector class that will return the appropriate DataTemplate based on the Item type
public class MyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate RegularTemplate { get; set; }
public DataTemplate AddTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item,
DependencyObject container)
{
if (item is AddGridItem)
return AddTemplate;
if (item is GridItem)
return RegularTemplate;
return base.SelectTemplateCore(item, container);
}
}
Define your dataTempaltes and a DataTemplateSelector as staticresources to use them in your GridView
<Page.Resources>
<DataTemplate x:Key="RegularTemplate">
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<Border BorderThickness="3" BorderBrush="White">
<StackPanel VerticalAlignment="Bottom" Background="LightSkyBlue">
<TextBlock Text="{Binding Subject}" Style="{StaticResource BaseTextBlockStyle}" Height="60" Margin="15,0,15,0" FontWeight="SemiBold"/>
<TextBlock Text="{Binding TargetDate}" Style="{StaticResource BaseTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10" FontSize="12"/>
</StackPanel>
</Border>
</Grid>
</DataTemplate>
<DataTemplate x:Key="AddItemTemplate">
<Border BorderThickness="3" BorderBrush="White" Background="DodgerBlue">
<FontIcon Glyph="" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White"/>
</Border>
</DataTemplate>
<local:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
RegularTemplate="{StaticResource RegularTemplate}"
AddTemplate="{StaticResource AddItemTemplate}">
</local:MyDataTemplateSelector>
</Page.Resources>
<Grid>
<GridView ItemsSource="{Binding GridItems}" ItemTemplateSelector="{StaticResource MyDataTemplateSelector}">
</GridView>
</Grid>

How to Make Content Hidden in Expander Windows Phone Control

I am playing around with an example of Expander Control from Windows Phone Toolkit (I am using it for wp7).
When I load up the stripped down version everything seems expanded. When I click on Customer Pizza or 2 nothing happens. I would like the sub stuff to be collapsed but I don't know how.
<phone:PhoneApplicationPage
x:Class="ExpanderViewSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<phone:PhoneApplicationPage.Resources>
<toolkit:RelativeTimeConverter x:Key="RelativeTimeConverter"/>
<DataTemplate x:Key="CustomHeaderTemplate">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" Stretch="None"/>
<TextBlock Text="{Binding Name}"
FontSize="{StaticResource PhoneFontSizeExtraLarge}"
FontFamily="{StaticResource PhoneFontFamilySemiLight}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="CustomExpanderTemplate">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" Stretch="None"/>
<TextBlock Foreground="{StaticResource PhoneSubtleBrush}" VerticalAlignment="Center"
FontSize="{StaticResource PhoneFontSizeNormal}">
<TextBlock.Text>
<Binding Path="DateAdded" Converter="{StaticResource RelativeTimeConverter}" StringFormat="Date added: {0}" />
</TextBlock.Text>
</TextBlock>
</StackPanel>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="WindowsPhoneGeek.com" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="ExpanderViewSample" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle2Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListBox Grid.Row="0" x:Name="listBox">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<toolkit:ExpanderView Header="{Binding}" Expander="{Binding}"
IsExpanded="False"
HeaderTemplate="{StaticResource CustomHeaderTemplate}"
ExpanderTemplate="{StaticResource CustomExpanderTemplate}"></toolkit:ExpanderView>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
List<CustomPizza> customPizzas = new List<CustomPizza>()
{
new CustomPizza()
{
Name = "Custom Pizza 1",
IsExpanded = false,
DateAdded = new DateTime(2010, 7, 8),
Image="Images/pizza1.png"
},
new CustomPizza() { Name = "Custom Pizza 2", DateAdded = new DateTime(2011, 2, 10), Image="Images/pizza2.png"}
};
this.listBox.ItemsSource = customPizzas;
// Important properties:
// IsExpanded
// Header
// Expander
// ItemsSource
// HeaderTemplate
// ExpanderTemplate
// ItemTemplate
// NonExpandableHeader
// IsNonExpandable
// NonExpandableHeaderTemplate
}
}
public class CustomPizza : INotifyPropertyChanged
{
private bool isExpanded;
public string Image
{
get;
set;
}
public string Name
{
get;
set;
}
public DateTime DateAdded
{
get;
set;
}
public bool IsExpanded
{
get
{
return this.isExpanded;
}
set
{
if (this.isExpanded != value)
{
this.isExpanded = value;
this.OnPropertyChanged("IsExpanded");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I also don't get what this really is for
ExpanderView Header="{Binding}" Expander="{Binding}"
I don't get what "binding" is referring too. It just seems to know which data to use but I don't know how it knows.
To change the expanded state of the expander view you can do the following
-register for tap event and add binding to IsExpanded (this will bind to the IsExpanded property of CustomPizza)
<toolkit:ExpanderView Header="{Binding}" Expander="{Binding}"
IsExpanded="{Binding IsExpanded}"
HeaderTemplate="{StaticResource CustomHeaderTemplate}"
ExpanderTemplate="{StaticResource CustomExpanderTemplate}"
Tap="expander_OnTap"></toolkit:ExpanderView>
-in the tap event switch the IsExpanded flag of the CustomPizza:
private void expander_OnTap(object sender, System.Windows.Input.GestureEventArgs e)
{
ExpanderView expander = sender as ExpanderView;
CustomPizza customPizza = expander.DataContext as CustomPizza;
customPizza.IsExpanded = !customPizza.IsExpanded;
}
Regarding the question about ExpanderView Header="{Binding}" Expander="{Binding}", when you set (or bind) the ItemsSource property of an ItemsControl to a list (ListBox is inheriting from a ItemsControl), the DataTemplate inside the ItemTemplate will be automatically set to each individual item. For example here you are setting it to a List of CustomPizza so each ItemTemplate DataContext will be a CustomPiza. So the ExpanderView will have the CustomPizza as DataContext. {Binding} will just pass the DataContext so like this whatever is inside the HEaderTemplate will get the same DataContext (CustomPizza ). If you had put {Binding Image} then the HeaderTemplate will just have the Image string as DataContext.