问题
I have a problem with bindings for DataTemplate
based on defined DataType
in ItemsControl
, when I want to bind to my custom user control.
For demonstration purposes, I\'ve created simple Item class example, where I have collection of items like this:
public class Item
{
public string ItemNameToBeSureWhatPropertyIsBound { get; set; }
}
In my ViewModel I create such collection, and expose it (with one item 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 custom user control is defined like this:
<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
in code behind:
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, when I try to bind to property of Item in DataTemplate for ItemsControl, which I\'m doing in MainWindow like this (note: I have dummy converter for debugging purposes only, returning 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}}\" />
<!--<Grid Background=\"Pink\">
<TextBlock Text=\"{Binding ItemNameToBeSureWhatPropertyIsBound, Converter={StaticResource MyDummyConverter}}\" Foreground=\"Black\" Height=\"30\" />
</Grid>-->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Grid Grid.Row=\"1\">
<my:ItemRowUserControl ItemName=\"{Binding DataContext.ExampleItem.ItemNameToBeSureWhatPropertyIsBound, ElementName=MyWindow, Converter={StaticResource MyDummyConverter}}\" />
</Grid>
</Grid>
Now, in case I bind to my custom ItemRowUserControl, the value I get into converter (and I see the same in Debug Output) is ItemRowUserControl itself. But if I bind to commented out code, everything works fine. Why is that, and how can I have custom control for DataTemplate so that bindings (offered by intellisense) will work? On the side note: binding to my ItemRowUserControl in grid row 1 (at the bottom) works fine, so I guess control is set to work as expected?
回答1:
The problem is that you explicitly set the DataContext
of your UserControl to itself:
DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}
Remove that assignment and write the ItemName
binding like this:
<TextBlock Text="{Binding ItemName,
RelativeSource={RelativeSource AncestorType=UserControl}}"/>
or like this
<TextBlock Text="{Binding ItemName, ElementName=ItemRowControl}"/>
来源:https://stackoverflow.com/questions/27834271/binding-to-custom-control-inside-datatemplate-for-itemscontrol