绑定到ItemsControl的DataTemplate内部的自定义控件 [英] Binding to custom control inside DataTemplate for ItemsControl

查看:59
本文介绍了绑定到ItemsControl的DataTemplate内部的自定义控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于 ItemsControl <中定义的 DataType DataTemplate 绑定,我遇到问题/ code>,当我想绑定到我的自定义用户控件时。

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; } 
}

在我的 ViewModel 中,我创建了这样的集合,并将其公开(单独比较一个项目):

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));
    }
}

我的自定义用户控件定义如下:

<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 后面的代码中:

...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); }
    }
}

问题是,当我尝试绑定到我在 MainWindow 中正在做的,这是ItemsControl的DataTemplate中Item的属性(请注意:我有一个虚拟转换器仅用于调试目的,返回值,仅此而已):

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>

现在,如果我绑定到自定义ItemRowUserControl,我进入转换器的值(我看到在Debug Output中相同)是ItemRowUserControl本身。但是,如果我绑定注释掉的代码,一切都会很好。为什么会这样,如何对DataTemplate进行自定义控件,以使绑定(由Intellisense提供)可以正常工作?在侧面说明:绑定到网格第1行(位于底部)中的ItemRowUserControl可以正常工作,因此我想控件设置为按预期方式工作?

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?

推荐答案

问题是您将UserControl的 DataContext 显式设置为其自身:

The problem is that you explicitly set the DataContext of your UserControl to itself:

DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}

删除该分配并编写 ItemName 绑定,如下所示:

Remove that assignment and write the ItemName binding like this:

<TextBlock Text="{Binding ItemName,
    RelativeSource={RelativeSource AncestorType=UserControl}}"/>

或类似的

<TextBlock Text="{Binding ItemName, ElementName=ItemRowControl}"/>

这篇关于绑定到ItemsControl的DataTemplate内部的自定义控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆