绑定到 ItemsControl 的 DataTemplate 内的自定义控件
Binding to custom control inside DataTemplate for ItemsControl
当我想绑定到 自定义用户控件 [=29] 时,基于 ItemsControl
中定义的 DataType
,DataTemplate
的绑定出现问题=].
出于演示目的,我创建了简单的 项目类 示例,其中我收集了如下项目:
public class Item
{
public string ItemNameToBeSureWhatPropertyIsBound { get; set; }
}
在我的 ViewModel 中,我创建了这样的集合,并将其公开(与一个项目单独比较):
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));
}
}
我的自定义用户控件是这样定义的:
<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>
...它在 代码后面有一个 DependencyProperty
:
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); }
}
}
问题是,当我尝试为 ItemsControl 绑定到 DataTemplate 中的 Item 属性时,我在 MainWindow 中这样做(注意:我有虚拟转换器仅用于调试目的,返回值,仅此而已):
<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>
现在,如果我绑定到我的自定义 ItemRowUserControl,我进入转换器的值(我在调试输出中看到相同值)是 ItemRowUserControl 本身。但是,如果我绑定到注释掉的代码,一切正常。为什么会这样,我怎样才能对 DataTemplate 进行自定义控制,以便绑定(由 intellisense 提供)起作用?旁注:绑定到网格第 1 行(底部)中的 ItemRowUserControl 工作正常,所以我猜控件设置为按预期工作?
问题是您将 UserControl 的 DataContext
显式设置为自身:
DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}
删除该分配并像这样编写 ItemName
绑定:
<TextBlock Text="{Binding ItemName,
RelativeSource={RelativeSource AncestorType=UserControl}}"/>
或者像这样
<TextBlock Text="{Binding ItemName, ElementName=ItemRowControl}"/>
当我想绑定到 自定义用户控件 [=29] 时,基于 ItemsControl
中定义的 DataType
,DataTemplate
的绑定出现问题=].
出于演示目的,我创建了简单的 项目类 示例,其中我收集了如下项目:
public class Item
{
public string ItemNameToBeSureWhatPropertyIsBound { get; set; }
}
在我的 ViewModel 中,我创建了这样的集合,并将其公开(与一个项目单独比较):
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));
}
}
我的自定义用户控件是这样定义的:
<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>
...它在 代码后面有一个 DependencyProperty
:
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); }
}
}
问题是,当我尝试为 ItemsControl 绑定到 DataTemplate 中的 Item 属性时,我在 MainWindow 中这样做(注意:我有虚拟转换器仅用于调试目的,返回值,仅此而已):
<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>
现在,如果我绑定到我的自定义 ItemRowUserControl,我进入转换器的值(我在调试输出中看到相同值)是 ItemRowUserControl 本身。但是,如果我绑定到注释掉的代码,一切正常。为什么会这样,我怎样才能对 DataTemplate 进行自定义控制,以便绑定(由 intellisense 提供)起作用?旁注:绑定到网格第 1 行(底部)中的 ItemRowUserControl 工作正常,所以我猜控件设置为按预期工作?
问题是您将 UserControl 的 DataContext
显式设置为自身:
DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}
删除该分配并像这样编写 ItemName
绑定:
<TextBlock Text="{Binding ItemName,
RelativeSource={RelativeSource AncestorType=UserControl}}"/>
或者像这样
<TextBlock Text="{Binding ItemName, ElementName=ItemRowControl}"/>