2016-09-20 3 views
0

Ich habe ein UserControl, das ein ViewModel mit einer Instanz meiner eigenen benutzerdefinierten Klasse hat, nennen Sie es Person. Dieses ViewModel wird als DataContext des Steuerelements festgelegt. Ich möchte dieses Steuerelement in meinem Hauptfenster verwenden, das in seinem ViewModel eine Liste des Typs Person namens People enthält. Ich rufe das Steuerelement in meinem Xaml wie folgt auf:Datenbindung eines Benutzersteuerelements in einem itemscontrol

<ItemsControl ItemsSource="{Binding People}"> 
    <ItemsControl.ItemsTemplate> 
     <DataTemplate> 
      <userControls:PersonDetails /> 
     </DataTemplate> 
    </ItemsControl.ItemsTemplate> 
</ItemsControl> 

Eigenschaften in der Steuerung sind auf diese Weise gebunden.

<TextBlock Text="{Binding Person.Name}" /> 

Wenn ich laufe ich die richtige Anzahl von Kontrollen für die Menge der Menschen in der Liste bekommen, aber keine Details bestückt sind. Ich weiß, ich mache etwas Einfaches falsch, kann es aber nicht finden. Bitte helfen Sie.

EDIT:

Mein Usercontrol XAML sieht wie folgt aus:

<UserControl x:Class="AddressBook.UserControls.PersonDetails" 
     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" 
     xmlns:local="clr-namespace:AddressBook.UserControls" 
     xmlns:vm="clr-namespace:AddressBook.ViewModels" 
     xmlns:enums="clr-namespace:AddressBook.Models" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="1000">  

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="40" /> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 

    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition Width="1*" /> 
    </Grid.ColumnDefinitions> 

    <TextBlock Style="{StaticResource PersonDetailHeader}" Text="Person Name:" /> 

    <TextBlock Style="{StaticResource PersonDetailValue}" Grid.Column="1" Text="{Binding Person.Name, 
       UpdateSourceTrigger=PropertyChanged}" /> 

    <TextBlock Style="{StaticResource PersonDetailHeader}" VerticalAlignment="Center" Grid.Row="1" Text="Street Address:" /> 

    <TextBlock Style="{StaticResource PersonDetailValue}" Grid.Row="1" Grid.Column="1" 
       Text="{Binding Person.StreetAddress, UpdateSourceTrigger=PropertyChanged}" /> 

    <TextBlock Style="{StaticResource PersonDetailHeader}" Grid.Row="2" Text="Town:" /> 

    <TextBlock Style="{StaticResource PeronDetailValue}" Grid.Row="2" Grid.Column="1" 
       Text="{Binding Person.Town, UpdateSourceTrigger=PropertyChanged}" /> 

    <TextBlock Style="{StaticResource PersonDetailHeader}" Grid.Row="3" Text="County:" /> 

    <TextBlock Style="{StaticResource PersonDetailValue}" Grid.Row="3" Grid.Column="1" 
       Text="{Binding Person.County, UpdateSourceTrigger=PropertyChanged}" /> 

    <TextBlock Style="{StaticResource PersonDetailHeader}" Grid.Row="4" Text="Postcode:" /> 

    <TextBlock Style="{StaticResource PersonDetailValue}" Grid.Row="4" Grid.Column="1" 
       Text="{Binding Person.Postcode, UpdateSourceTrigger=PropertyChanged}" /> 

    <TextBlock Style="{StaticResource PersonDetailHeader}" Grid.Row="5" Text="Phone:" /> 

    <TextBlock Style="{StaticResource PersonDetailValue}" Grid.Row="5" Grid.Column="1" 
       Text="{Binding Person.Phone, UpdateSourceTrigger=PropertyChanged}" /> 

    <StackPanel Grid.Row="7" Grid.ColumnSpan="2" HorizontalAlignment="Center" Orientation="Horizontal"> 
     <Button Style="{StaticResource ButtonStyle}" Content="Click" Command="{Binding ButtonClickCommand}" /> 

    </StackPanel> 
</Grid> 

Usercontrol Ansichtsmodell:

public class PersonDetailsViewModel 
{ 
    public Person Person { get; set; } 

    public Command ButtonClickCommand { get; } 

    public PersonDetailsViewModel() 
    { 
     ButtonClickCommand = new Command(ButtonClick); 
    } 

    private void ButtonClick(object obj) 
    { 
     throw new NotImplementedException(); 
    } 

UserControl.xaml.cs:

public partial class PersonDetails : UserControl 
{ 
    public PersonDetails() 
    { 
     InitializeComponent(); 
    } 
} 

Person.cs

public class Person : BaseModel 
{ 
    public string Name 
    { 
     get { return name; } 
     set 
     { 
      name = value; 

      NotifyPropertyChanged(); 
     } 

etc ....

MainViewModel:

public class MainViewModel : BaseViewModel 
{ 
    public ObservableCollection<Person> People { get; } 
     = new ObservableCollection<Person>(); 

    public MainViewModel() 
    { 
     PopulatePeople(); 
    } 
} 
+0

Hören Sie Daten Kontext geändert Ereignis für die Benutzersteuerung und überprüfen Sie, welche Datenkontext Sie bekommen. Ob es die richtige ist, die Sie wollten, d. H. Ihre Klasse Person? – Versatile

+0

Ash - keine verbindlichen Fehler in der Ausgabe. –

+0

Silvermind - Danke, aber das hat nicht funktioniert. Vielseitig - Das DataContextChanged-Ereignis wird nicht einmal ausgelöst, sodass es eindeutig nicht gesetzt wird. –

Antwort

1

Jetzt ich Verstehen Sie, warum Sie die PersonDetailsViewModel in der UserControl XAML erstellt haben, und was das Problem mit dem Befehl war.

Der einfachste Weg, dies zu beheben, ist MainViewModel.People eine Sammlung von PersonDetailsViewModel anstelle von Person zu machen. Das würde ich tun.

Aber wenn Sie MainViewModel.People so lassen wollen, wie es ist, während Sie immer noch PersonDetailsViewModel in Ihrem UserControl verwenden, macht das Sinn für mich. Sie können dies tun:

.xaml

<UserControl 
    x:Class="AddressBook.UserControls.PersonDetails" 
    DataContextChanged="PersonDetails_DataContextChanged" 

    ...etc... 

    > 

    <!-- Give the Grid a name... --> 
    <Grid x:Name="OuterGrid"> 

XAML.cs

public PersonDetails() 
{ 
    InitializeComponent(); 
} 

private void PersonDetails_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) 
{ 
    // ...so we can give the Grid a different DataContext 
    OuterGrid.DataContext = new PersonDetailsViewModel { 
     Person = (Person)this.DataContext 
    }; 
} 

Jetzt wird es eine Person für seine DataContext, erben aber intern wird es eine PersonDetailsViewModel Basis verwenden, um auf diesem Person.

0

nicht sicher, ob das, was Sie zu tun versuchen. Wenn Sie nur in Ihrem Menschen Liste vorhanden einige carac jeder Person anzeigen möchten Sie tun können:

 <Grid> 
      <ItemsControl ItemsSource="{Binding People}"> 
        <ItemsControl.ItemTemplate> 
          <DataTemplate> 
            <Grid Margin="0,0,0,5"> 
              <Grid.ColumnDefinitions> 
                <ColumnDefinition Width="*" /> 
                <ColumnDefinition Width="100" /> 
              </Grid.ColumnDefinitions> 
              <TextBlock Text="{Binding Name}" /> 
              <TextBlock Grid.Column="1" Text="{Binding Age}" /> 
            </Grid> 
          </DataTemplate> 
        </ItemsControl.ItemTemplate> 
      </ItemsControl> 
    </Grid> 

, die Sie auf die Eigenschaft Name jedes Elements der Liste Text binden, so auf den Namen von jedem Person Ihrer Liste. Da Ihre ItemsSource bereits an Personen gebunden ist, befindet sich die Bindung Ihrer Elemente bereits auf jeder Person Ihrer Liste. Sie sollten also Ihre Eigenschaften direkt als {Binding Name} und nicht {Binding Person.Name} aufrufen.

+0

Danke für die Hilfe, aber es gibt andere Felder, die in der Benutzersteuerung wie eine Kontaktkarte angezeigt werden, ich habe sie einfach weggelassen, weil keine von ihnen angezeigt wird und alle auf die gleiche Weise gebunden sind. –

+0

Ist Ihr Benutzersteuerelement ein anderes Fenster, das Sie mit der ausgewählten Person ausfüllen? Oder ist es ein Raster, das zu jeder Zeit alle Ihre Personen und deren Informationen enthält? – Belterius

+0

Ich habe meine Antwort so bearbeitet, dass sie so viel Feld wie Sie wollen – Belterius

Verwandte Themen