2015-01-08 15 views
6

Ich habe ein Problem mit Bindungen für DataTemplate auf Basis definierter DataType in ItemsControl, wenn ich mein benutzerdefinierten Steuerelement binden möge.Bindung an individueller Steuerung innerhalb Datatemplate für Items

Zu Demonstrationszwecken habe ich Item-Klasse Beispiel einfach erstellt, wo ich Sammlung von Gegenständen wie dieses:

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

In meinem Ansichtsmodell ich eine solche Sammlung zu erstellen, und es aussetzen (mit ein Element zum Vergleich separat):

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

Meine individuelle Benutzersteuerung ist wie folgt definiert:

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

... und es hat einen DependencyProperty in Code hinter:

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

Das Problem ist, wenn ich an das Eigentum der Artikel zu binden versuchen in Datatemplate für Itemscontrol, die ich bin tun in Mainwindow wie folgt aus (Anmerkung: ich habe Dummy-Konverter für Debugging-Zwecke nur, den Wert der Rückkehr zurück, und nichts mehr):

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

Wenn ich jetzt an mein benutzerdefiniertes ItemRowUserControl binde, ist der Wert, den ich in den Konverter bekomme (und ich sehe dasselbe in der Debug-Ausgabe), ItemRowUserControl selbst. Aber wenn ich an auskommentierten Code binde, funktioniert alles gut. Warum ist das so, und wie kann ich benutzerdefinierte Kontrolle für DataTemplate haben, damit Bindungen (die von Intellisense angeboten werden) funktionieren? Auf der Randnotiz: Die Bindung an mein ItemRowUserControl in der ersten Zeile (unten) funktioniert gut, also denke ich, dass die Steuerung so funktioniert wie erwartet?

Antwort

5

Das Problem ist, dass man sich ausdrücklich DataContext Ihrer Usercontrol selbst gesetzt:

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

diese Zuordnung entfernen und schreiben die ItemName wie diese Bindung:

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

oder wie diese

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

Vielen Dank, das funktioniert wie erwartet. Können Sie bitte den RelativeSource-Teil der Bindung erklären? Die Bindung mit ElementName in Ihrer Antwort macht für mich Sinn. Danke noch einmal. –

+1

Bitte beachten Sie [Online-Dokumentation] (http://msdn.microsoft.com/en-us/library/system.windows.data.binding.relativesource.aspx) auf MSDN. In beiden Fällen wird die UserControl-Instanz als Quellobjekt der Bindung festgelegt. – Clemens

+1

@JanezLukan, das bedeutet relatives Nachschlagen in der Kontrollstruktur, bis die Kontrolle vom Typ 'UserControl' gefunden wird und die Suche nach oben erfolgt, da dort 'AncestorType' steht –

Verwandte Themen