2015-01-08 9 views
6

ためのDataTemplate内のカスタムコントロールにバインド。は、私は私の<strong>カスタムユーザーコントロール</strong>にバインドするとき、私は、<code>ItemsControl</code>で定義された<code>DataType</code>に基づいて<code>DataTemplate</code>のバインディングに問題があるのItemsControl

デモンストレーションの目的のために

、私はこのようなアイテムのコレクションを持っているシンプルなItemクラスたとえば、作成しました:私は、このようなコレクションを作成し、(とそれを公開し、私ののViewModel

public class Item 
{ 
    public string ItemNameToBeSureWhatPropertyIsBound { get; set; } 
} 

を比較のための一つのアイテム別途):

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> 

...それが持っている1 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内のアイテムのプロパティにバインドしようとすると問題がありますでやっメインウィンドウこのような(注:私はダミー、デバッグ目的でのみバック値を返すためのコンバータ、およびより多くの何を持っている):

<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自体です。しかし、私がコメントアウトしたコードにバインドすると、すべて正常に動作します。それはなぜですか、また、バインディング(intellisenseによって提供される)が機能するように、DataTemplateのカスタムコントロールをどのように持つことができますか?サイドノート:グリッドの行1(下側)のItemRowUserControlへのバインディングは正常に動作するので、コントロールは期待通りに動作するように設定されていると思いますか?

答えて

5

問題は、明示的にそれ自体にユーザーコントロールのDataContextを設定することです:

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

は、その割り当てを削除し、次のように結合ItemName書く:

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

またはこのような

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

ありがとう、これは期待どおりに動作します。バインディングのRelativeSource部分について説明できますか?あなたの答えにElementNameを使ってバインドすると、私にとって意味があります。再度、感謝します。 –

+1

MSDNの[オンラインドキュメント](http://msdn.microsoft.com/en-us/library/system.windows.data.binding.relativesource.aspx)を参照してください。どちらの場合でも、UserControlインスタンスはバインディングのソースオブジェクトとして設定されます。 – Clemens

+1

@ JanezLukanこれは、 'UserControl'型のコントロールを検出し、' AncestorType'と言うためにルックアップが上になるまでコントロールツリー内で比較的ルックアップを意味します。 –

関連する問題

 関連する問題