WPF DataTemplate, TemplateSelectors, ContentPresenter based on SelectedItem - c#

I am very confused what to use and how to start implementations, but I want is based on a Enum property when changed a certain grid should display.
Currently I have like 20 grids, working with visibility when the property change.
This is not ideal for 2 things. All 20 grids will bind from startup and it isnot good for performance. Secondly some "Grids" are the same for some values of the enum property. So I have duplicate code in some grids.
Now what I have is an enum:
public enum MyEnumsForDropDown
{
Enum1= 1,
Enum2= 2,
Enum3= 3,
Enum4= 4,
Enum5= 5
}
My Object in my ViewModel, which I bind to is for :
Public class MyObject
{
private Enums.MyEnumsForDropDown _myChosenEnum;
public Enums.MyEnumsForDropDown MyChosenEnum
{
get { return _myChosenEnum; }
set
{
_myChosenEnum = value;
this.NotifyPropertyChanged( x => x.MyChosenEnum );
}
}
}
My XAML:
<ComboBox ItemsSource="{Binding CollectionOfEnums}"
DisplayMemberPath="Value" SelectedValuePath="Key" SelectedValue="{Binding
MyObject.MyChosenEnum}"></ComboBox>
<Grid Grid.Row="1" Grid.Column="3" Visibility="{Binding
Path=MyObject.MyChoseEnum, Converter={StaticResource
EnumToVisibleCollapseConverter}, ConverterParameter={x:Static
myenumsNameSpace:Enums+MyEnumsForDropDown.Enum1}}">
<TextBlock Content"This Grid displays when Enum1 is chosen"/>
</Grid>
<Grid Grid.Row="1" Grid.Column="3" Visibility="{Binding
Path=MyObject.MyChoseEnum, Converter={StaticResource
EnumToVisibleCollapseConverter}, ConverterParameter={x:Static
myenumsNameSpace:Enums+MyEnumsForDropDown.Enum2}}">
<TextBlock Content"This Grid displays when Enum2 is chosen"/>
</Grid>
How do I change the Grids to work somehow like ContentPresenters or DataTemplates or whatever I need to use depended on when the property MyChosenEnum changes in my object??

You could define a DataTemplate for each enum value and then use a ContentControl with a Style to display the correct one:
<ContentControl Content="{Binding MyObject.MyChosenEnum}">
<ContentControl.Resources>
<DataTemplate x:Key="Enum1">
<Grid />
</DataTemplate>
<DataTemplate x:Key="Enum2">
<Grid />
</DataTemplate>
</ContentControl.Resources>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding MyObject.MyChosenEnum}"
Value="{x:Static myenumsNameSpace:Enums+MyEnumsForDropDown.Enum1}">
<Setter Property="ContentTemplate" Value="{StaticResource Enum1}" />
</DataTrigger>
<DataTrigger Binding="{Binding MyObject.MyChosenEnum}"
Value="{x:Static myenumsNameSpace:Enums+MyEnumsForDropDown.Enum2}">
<Setter Property="ContentTemplate" Value="{StaticResource Enum2}" />
</DataTrigger>
<!-- and so on for each enum value -->
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
Or you could use a DataTemplateSelector:
public class YourSelector : DataTemplateSelector
{
public DataTemplate Enum1 { get; set; }
public DataTemplate Enum2 { get; set; }
//...
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
MyEnumsForDropDown value = (MyEnumsForDropDown)item;
switch(value)
{
case MyEnumsForDropDown.Enum1:
return Enum1;
case MyEnumsForDropDown.Enum2:
return Enum2;
}
return base.SelectTemplate(item, container);
}
}
<Grid>
<Grid.Resources>
<DataTemplate x:Key="Enum1">
<Grid />
</DataTemplate>
<DataTemplate x:Key="Enum2">
<Grid />
</DataTemplate>
<local:YourSelector x:Key="selector" Enum1="{StaticResource Enum1}" Enum2="{StaticResource Enum2}" />
</Grid.Resources>
<ContentControl Content="{Binding MyObject.MyChosenEnum}"
ContentTemplateSelector="{StaticResource selector}" />
</Grid>

Related

ItemSource value can evaluate to decide the style between label or radio buttons

I am looking for a wpf example of when Itemsource is more than 1 then it can creates radio button dynamically. If it just one value in Itemsource then it should be label instead of radio buttons. Do I have to write converter which can pass the value of Itemsource and control the style between label and radio button. If anyone can provide example then it will be great.
You may use a ItemContainerStyle with a DataTrigger on the Count property of the ItemsControl's Items.
The Style would chose between two different ContentTemplates, depending on whether there is exactly one item or not.
<ItemsControl ItemsSource="{Binding ...}">
<ItemsControl.Resources>
<DataTemplate x:Key="DefaultItemTemplate">
<RadioButton Content="{Binding ...}"/>
</DataTemplate>
<DataTemplate x:Key="SingleItemTemplate">
<Label Content="{Binding ...}"/>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="ContentTemplate"
Value="{StaticResource DefaultItemTemplate}"/>
<Style.Triggers>
<DataTrigger
Binding="{Binding Items.Count,
RelativeSource={RelativeSource AncestorType=ItemsControl}}"
Value="1">
<Setter Property="ContentTemplate"
Value="{StaticResource SingleItemTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
The ContentControl creates a control and chooses the correct DataTemplate for it based on its Type. So you don't need a converter:
<ContentControl Content="{Binding Child}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type local:Type1}">
<Label Content="{Binding ItemText}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Type2}">
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding ItemText}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
This code reacts to different types of Child property inside VM:
public BaseType Child { get; set; }
Data types:
public class BaseType { }
public class Type1 : BaseType
{
public string ItemText { get; set; }
}
public class Type2 : BaseType
{
public ObservableCollection<Type1> Items { get; } = new ObservableCollection<Type1>();
}
for example if you set Child to a Type1 it will show you one label
Child = new Type1 { ItemText = "hello" };
or if you set it to Type2 you will have your radiobutton collection:
var t = new Type2();
t.Items.Add(new Type1 { ItemText = "hello" });
t.Items.Add(new Type1 { ItemText = "world" });
Child = t;

Struggling to template a WPF MenuItem's Icon with control

Following on from a previous question here, I'm struggling to style a MenuItem's Icon with a control I have that inserts icon images based upon a string dependency property.
Initially I started with:
<ContextMenu ItemsSource="{Binding MenuItems}">
<ContextMenu.Resources>
<Style TargetType="MenuItem">
...
<Setter Property="Icon">
<local:StringToIcon IconName="{Binding IconName}" />
</Setter>
</Style>
</ContextMenu.Resources>
</ContextMenu>
This had the predictable effect of only displaying one of the icons in the menu, usually the last one, as the instance was shared around.
I then tried the non-shared resource approach:
<ContextMenu ItemsSource="{Binding MenuItems}">
<ContextMenu.Resources>
<local:StringToIcon x:Key="MenuIcon" x:Shared="False" IconName="{Binding IconName}" />
<Style TargetType="MenuItem">
...
<Setter Property="Icon" Value="{StaticResource MenuIcon} />
</Style>
</ContextMenu.Resources>
</ContextMenu>
This had no effect. It didn't offer me x:Shared in Intellisense, so I wonder if that's an invalid property here.
Out of desperation, I threw the thing into a template:
<Setter Property="Icon">
<Setter.Value>
<ContentControl>
<ContentControl.Template>
<ControlTemplate>
<local:StringToIcon IconName="{Binding IconName}" />
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
</Setter.Value>
</Setter>
Again, no effect. My StringToIcon looks like this at the moment, hard-coded with a single image to check the problem doesn't lie there. (Or does it?)
<UserControl x:Class="RAP.Admin3.Components.StringToIcon"
...
>
<Image DataContext="{Binding ElementName=StringIconControl}" Source="pack://application:,,,/Resources/Icons/lorry.png"/>
</UserControl>
How do I get this darn thing to template and allow multiple uses? It's probably something basic I'm overlooking.
I've looked at various similar questions, and most seem to have success with the non-shared resource method.
Edit: Let me add substantially more code as requested. I've come up with a minimal replication of the problem:
The context menu is part of a TreeView resource.
<UserControl x:Class="MyApp.ItemHierarchy"
...
Name="ItemHierarchyControl">
<Grid>
<TreeView ItemsSource="{Binding ElementName=ItemHierarchyControl, Path=Items}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:HierarchyItem}" ItemsSource="{Binding Subitems}">
<StackPanel Orientation="Horizontal" Margin="0,1,4,1">
<TextBlock Text="My text" VerticalAlignment="Center" />
<StackPanel.ContextMenu>
<ContextMenu ItemsSource="{Binding MenuItems}">
<ContextMenu.Resources>
<local:StringToIcon x:Key="MenuIcon" x:Shared="False" IconName="{Binding IconName}" />
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Path=Name}" />
<Setter Property="Icon" Value="{StaticResource MenuIcon}" />
</Style>
</ContextMenu.Resources>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
</UserControl>
This is backed by a dependency property for the items.
public ObservableCollection<HierarchyItem> Items
{
get { return (ObservableCollection<HierarchyItem>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection<HierarchyItem>), typeof(ItemHierarchy), new PropertyMetadata(new ObservableCollection<HierarchyItem>()));
StringToIcon is also backed by a string dependency property for the icon name, which is summarily ignored because of the hard-coded image at the moment.
HierarchyItems are simple for the example:
public ObservableCollection<HierarchyItem> Subitems { get; set; }
public ObservableCollection<BindableMenuItem> MenuItems { get; set; }
Just to get this proof working, I attached the ItemHierarchy to some properties of the main window:
public ObservableCollection<BindableMenuItem> MenuItems { get; set; }
public ObservableCollection<HierarchyItem> IHItems { get; set; }
public MainWindow()
{
MenuItems = new ObservableCollection<BindableMenuItem>();
MenuItems.Add(new BindableMenuItem("Item", null));
MenuItems.Add(new BindableMenuItem("Item", null));
MenuItems.Add(new BindableMenuItem("Item", null));
MenuItems.Add(new BindableMenuItem("Item", null));
IHItems = new ObservableCollection<HierarchyItem>();
IHItems.Add(new HierarchyItem() { MenuItems = this.MenuItems });
InitializeComponent();
}
Edit 2: Here's BindableMenuItem also:
public class BindableMenuItem
{
public BindableMenuItem(string name, ICommand command)
{
this.Name = name;
this.Command = command;
}
public string Name { get; set; }
public ICommand Command { get; set; }
public string IconName { get; set; }
public ObservableCollection<BindableMenuItem> Children { get; set; }
}
Try to move the StringToIcon to <TreeView.Resources>:
<TreeView ItemsSource="{Binding ElementName=ItemHierarchyControl, Path=Items}">
<TreeView.Resources>
<local:StringToIcon x:Key="MenuIcon" x:Shared="False" IconName="{Binding IconName}" />
<HierarchicalDataTemplate DataType="{x:Type local:HierarchyItem}" ItemsSource="{Binding Subitems}">
<StackPanel Orientation="Horizontal" Margin="0,1,4,1">
<TextBlock Text="My text" VerticalAlignment="Center" />
<StackPanel.ContextMenu>
<ContextMenu ItemsSource="{Binding MenuItems}">
<ContextMenu.Resources>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Path=Name}" />
<Setter Property="Icon" Value="{StaticResource MenuIcon}" />
</Style>
</ContextMenu.Resources>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>

Refresh DataGrid data on TreeViewItem selection change

I was able to implement Tree View using the link
Now I have attached the below Data Grid to it for displaying the city details like Area, Population, TimeZone etc.I was able to receive the event IsSelected upon selecting the City name from the treeview using example. But how do I bind the data of City model (Area, Population, TimeZone ) to a datagrid in the .xaml ? I tried using the CityViewModel directly but it never populates the data.CityViewModel has an observableCollection of "CityTown"( with props like Area, Population, TimeZone etc) property called "CityTowns" which I am populating when IsSelected is fired.My Tree View only has Region -> State -> City hierarchy. City towns should be displayed in grid not in tree.
//DemoWindow.xaml content:
<TabControl>
<TabItem Header="Load Towns">
<StackPanel Orientation="Horizontal">
<advanced: LoadOnDemandControl/>
<DataGrid ItemsSource="{Binding Path=local.CityViewModel.CityTowns}"
AutoGenerateColumns="False" IsReadOnly="True"
>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=Popluation}" Header="Popluation"/>
<DataGridTextColumn Binding="{Binding Path=Revenue}" Header="Revenue"/>
<DataGridTextColumn Binding="{Binding Path=TimeZone}" Header="TimeZone"/>
<DataGridTextColumn Binding="{Binding Path=Area}" Header="Area"/>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</TabItem>
</TabControl>
//LoadOnDemandCcontrol.xaml:
<TreeView ItemsSource="{Binding Regions}">
<TreeView.ItemContainerStyle>
<!--
This Style binds a TreeViewItem to a TreeViewItemViewModel.
-->
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="FontWeight" Value="Normal" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate
DataType="{x:Type local:RegionViewModel}"
ItemsSource="{Binding Children}"
>
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Margin="3,0" Source="Images\Region.png" />
<TextBlock Text="{Binding RegionName}" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
DataType="{x:Type local:StateViewModel}"
ItemsSource="{Binding Children}"
>
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Margin="3,0" Source="Images\State.png" />
<TextBlock Text="{Binding StateName}" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:CityViewModel}">
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Margin="3,0" Source="Images\City.png" />
<TextBlock Text="{Binding CityName}" />
</StackPanel>
</DataTemplate>
</TreeView.Resources>
</TreeView>
//CityTown.cs content:
public class CityTown
{
public int Area { get; set; }
public int Population { get; set; }
public string TimeZone { get; set; }
public int Revenue { get; set; }
public virtual City City { get; set; }
}
//CityViewModel.cs cocntent
public class CityViewModel : TreeViewItemViewModel
{
readonly City _city;
public CityViewModel(City city, StateViewModel parentState)
: base(parentState, false)
{
_city = city;
}
public string CityName
{
get { return _city.CityName; }
}
private ObservableCollection<CityTown> _CityTowns;
public ObservableCollection<CityTown> CityTowns
{
get { return Database.GetTowns(CityName); }
set { _CityTowns = value; }
}
}
//LoadOnDemandDemoControl.xaml.cs content:
public partial class LoadOnDemandDemoControl : UserControl
{
public LoadOnDemandDemoControl()
{
InitializeComponent();
Region[] regions = Database.GetRegions();
CountryViewModel viewModel = new CountryViewModel(regions);
base.DataContext = viewModel;
}
}
I solved it by defining the SelectedValuePath property for TreeView xaml element class and used the same in DataGrid element -> ItemsSoruce property -> Path -> SelectedItem.ViewModelDataCollection.

Combobox-Datatemplate & Selection TextBox

I have a combobox which has 2 items. Each item is an objet deriving from a common interface. There is a DisplayText property on each object. Each object is templated so as to have a different visual. Everything works fine, except while selecting one of those objects, the visual is getting displayed in the combobox textbox. I want it to display the SelectedText property of the selected object in the textbox and the DisplayText inside the item template. How do I specify my binding for that please?
Here is my code:
public interface IMyDate
{
string DisplayText { get; }
string SelectedText { get; }
}
public class TodayMinus1 : IMyDate
{
public string DisplayText { get { return "Yesterday"; } }
public string SelectedText{get { return DateTime.Today.AddDays(-1).ToString(); }}
}
public class Today : IMyDate
{
public string DisplayText { get { return "TODAY"; } }
public string SelectedText { get { return DateTime.Today.ToString(); } }
}
public class MyMainViewModel
{
public MyMainViewModel()
{
MyDates = new List<IMyDate>() {new Today(), new TodayMinus1()};
}
public List<IMyDate> MyDates { get; set; }
public IMyDate SelectedDate { get; set; }
}
<ComboBox MaxHeight="26" VerticalAlignment="Center" x:Name="contextDropdown" ItemsSource="{Binding MyDates}" SelectedItem="{Binding SelectedDate}" Grid.Column="1" Width="150" Margin="5">
<ComboBox.Resources>
<DataTemplate DataType="{x:Type local:TodayMinus1}">
<TextBlock Text="{Binding DisplayText}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Today}">
<TextBlock Text="{Binding DisplayText}"/>
</DataTemplate>
</ComboBox.Resources>
</ComboBox>
Please note that this is an oversimplified example and I have implemented INPC for all my objects.
Try this:
<ComboBox MaxHeight="26" VerticalAlignment="Center" x:Name="contextDropdown" ItemsSource="{Binding MyDates}"
SelectedItem="{Binding SelectedDate}" Grid.Column="1" Width="150" Margin="5">
<ComboBox.Resources>
<DataTemplate DataType="{x:Type local:TodayMinus1}">
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="{Binding DisplayText}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType=ComboBoxItem}}" Value="{x:Null}">
<Setter Property="Text" Value="{Binding SelectedText}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Today}">
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="{Binding DisplayText}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType=ComboBoxItem}}" Value="{x:Null}">
<Setter Property="Text" Value="{Binding SelectedText}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ComboBox.Resources>
</ComboBox>
Added a DataTrigger inside the DataTemplate to achieve your requirement. Try this.
<ComboBox MaxHeight="26" VerticalAlignment="Center" x:Name="contextDropdown" ItemsSource="{Binding MyDates}" SelectedItem="{Binding SelectedDate}" Grid.Column="1" Width="150" Margin="5">
<ComboBox.Resources>
<DataTemplate DataType="{x:Type local:TodayMinus1}">
<TextBlock Text="{Binding DisplayText}" x:Name="DisplayBox"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}" Value="{x:Null}">
<Setter TargetName="DisplayBox" Property="Text" Value="{Binding SelectedText}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Today}">
<TextBlock Text="{Binding DisplayText}" x:Name="DisplayBox"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}" Value="{x:Null}">
<Setter TargetName="DisplayBox" Property="Text" Value="{Binding SelectedText}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.Resources>
</ComboBox>

Bind to index in ItemsControl from DataTemplate

I have a simple class which creates a list of objects:
namespace TestWPF2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public ObservableCollection<TestObj> SomeList { get; set; }
public string WindowTitle { get; set; }
public MainWindow()
{
this.DataContext = this;
WindowTitle = "People";
SomeList = new ObservableCollection<TestObj>();
SomeList.Add(new TestObj("Bob"));
SomeList.Add(new TestObj("Jane"));
SomeList.Add(new TestObj("Mike"));
InitializeComponent();
}
}
}
The TestObj class is as follows:
namespace TestWPF2
{
public class TestObj
{
public string FirstName { get; set; }
public TestObj(string firstName)
{
this.FirstName = firstName;
}
}
}
I then attempt to display each item in the list with the following:
<Window x:Class="TestWPF2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestWPF2"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type local:TestObj}">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Pos: "/>
<TextBlock x:Name="posText"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name: "/>
<TextBlock Text="{Binding FirstName}"/>
</StackPanel>
</StackPanel>
<!-- THESE TRIGGERS DONT WORK -->
<DataTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Text" Value="First" TargetName="posText"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Text" Value="Second" TargetName="posText"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="3">
<Setter Property="Text" Value="Third" TargetName="posText"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</Window.Resources>
<StackPanel>
<TextBlock Text="{Binding Title}"/>
<ItemsControl HorizontalAlignment="Stretch"
ItemsSource="{Binding SomeList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</Window>
What I would like to display is something like:
Pos: First
Name: Bob
Pos: Second
Name: Jane
etc.
It's pretty straight-forward to bind to the FirstName property of each item in the list, but I would also like bind to the index in the list. I know I can do this from inside an ItemsControl using ItemsControl.AlternationIndex, but how do I link to the AlternationIndex from within in DataTemplate?
You need to understand that your context is TestObj and with your trigger, you are basicly checking the value of a property named ItemsControl which should have a property AlternationIndex.
You should changed the context of your triggers with a RelativeSource binding to the control that hold your object, named the ContentPresenter:
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)" Value="0">
<Setter Property="Text" Value="First" TargetName="posText"/>
</Trigger>
<!--- here be the other triggers -->
</DataTemplate.Triggers>
Hope this helps..

Categories