I have a binding problem for a DataTemplate based on the specific DataType in the ItemsControl when I want to bind to a custom user element .
For demonstration purposes, I created a simple example of a Class Element , where I have a collection of such elements:
public class Item { public string ItemNameToBeSureWhatPropertyIsBound { get; set; } }
In my ViewModel I create such a collection and expose it (one element for comparison separately):
public class MainWindowViewModel : INotifyPropertyChanged { private ObservableCollection<Item> _items; private Item _exampleItem; public MainWindowViewModel() { Items = new ObservableCollection<Item>(new[] { new Item { ItemNameToBeSureWhatPropertyIsBound = "Me" }, new Item { ItemNameToBeSureWhatPropertyIsBound = "MySelf" }, new Item { ItemNameToBeSureWhatPropertyIsBound = "Ich" }, }); ExampleItem = Items.LastOrDefault(); } public ObservableCollection<Item> Items { get { return _items; } set { _items = value; OnPropertyChanged(); } } public Item ExampleItem { get { return _exampleItem; } set { _exampleItem = value; OnPropertyChanged();} } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } }
My user control is defined as follows:
<UserControl x:Class="WpfDataTemplate.ItemRowUserControl" 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" mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="300" x:Name="ItemRowControl" DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}"> <Grid Background="Yellow" Height="40"> <TextBlock Text="{Binding ItemName}" Foreground="Black"/> </Grid> </UserControl>
... and it has one DependencyProperty per code for :
public partial class ItemRowUserControl : UserControl { public ItemRowUserControl() { InitializeComponent(); } public static readonly DependencyProperty ItemNameProperty = DependencyProperty.Register( "ItemName", typeof (string), typeof (ItemRowUserControl), new PropertyMetadata(default(string))); public string ItemName { get { return (string) GetValue(ItemNameProperty); } set { SetValue(ItemNameProperty, value); } } }
The problem is that when I try to bind the Item property in the DataTemplate for the ItemsControl, which I do in MainWindow , like this (note: I have a dummy converter for debugging purposes only, returning the value back, and nothing more):
<Window.DataContext> <my:MainWindowViewModel /> </Window.DataContext> <Window.Resources> <my:MyDummyConverter x:Key="MyDummyConverter" /> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="50" /> </Grid.RowDefinitions> <ItemsControl Name="ItemsControl" ItemsSource="{Binding Items}" Grid.Row="0" Background="Red"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate DataType="{x:Type my:Item}"> <my:ItemRowUserControl ItemName="{Binding ItemNameToBeSureWhatPropertyIsBound, Converter={StaticResource MyDummyConverter}}" /> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> <Grid Grid.Row="1"> <my:ItemRowUserControl ItemName="{Binding DataContext.ExampleItem.ItemNameToBeSureWhatPropertyIsBound, ElementName=MyWindow, Converter={StaticResource MyDummyConverter}}" /> </Grid> </Grid>
Now, if I bind myself to my custom ItemRowUserControl, the value that I get in the converter (and I see the same thing in Debug Output) is the ItemRowUserControl itself. But if I get attached to the commented code, everything will be fine. Why is this, and how can I customize the control for a DataTemplate so that the bindings (suggested by intellisense) work? On the side note: binding to my ItemRowUserControl in grid line 1 (bottom) is working fine, so I think the control is set up to work as expected?