2016-09-20 11 views
0

У меня есть UserControl, у которого есть ViewModel, содержащий экземпляр моего собственного пользовательского класса, назовите его Person. Этот ViewModel устанавливается как элемент управления DataContext. Я хочу использовать этот элемент управления в своем главном окне, которое имеет в своем представлении ViewModel список типов Person, называемых People. Я вызываю элемент управления в своем xaml следующим образом:Сопоставление пользовательского элемента управления внутри элемента управления

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

Свойства в элементе управления связаны таким образом.

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

Когда я запустил, я получаю правильное количество элементов управления для количества людей в списке, но данные не заполняются. Я знаю, что делаю что-то простое, но не могу найти его. Пожалуйста помоги.

EDIT:

Моя UserControl XAML выглядит следующим образом:

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

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

и т.д ....

MainViewModel:

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

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

Прослушать контекст данных, измененный для пользовательского контроля, и проверить, какой контекст данных вы получаете. Правильно ли это, что вы хотели, т. Е. Ваш класс Person? – Versatile

+0

Пепел - отсутствие ошибок привязки в выводе. –

+0

Silvermind - Спасибо, но это не сработало. Универсальный - событие DataContextChanged даже не срабатывает, поэтому он явно не устанавливается. –

ответ

1

Теперь я понять, почему вы создавали PersonDetailsViewModel в XAML UserControl, и в чем проблема с командой.

Самый простой способ исправить это - сделать MainViewModel.People коллекцией PersonDetailsViewModel вместо Person. Это то, что я сделал бы.

Но если вы хотите оставить MainViewModel.People, так как он все еще использует PersonDetailsViewModel внутри вашего UserControl, это имеет смысл для меня. Вы можете сделать это:

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

Теперь он будет наследовать Person для своих DataContext, но внутренне он будет использовать PersonDetailsViewModel на основе этого Person.

0

Не уверен, что это то, что вы пытаетесь сделать. Если вы только хотите отобразить некоторые Carac каждого из присутствующих в свой список людей, которых вы могли бы сделать:

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

Это будет связывать вас текст на имя свойства каждого элемента в списке, так что на имя каждого Лицо вашего списка. Поскольку ваш ItemsSource уже привязан к людям, привязка ваших товаров уже включена в каждое лицо вашего списка, поэтому вы должны называть свои свойства непосредственно как {Binding Name}, а не {Binding Person.Name}

+0

Спасибо за помощь, но есть другие поля для отображения внутри пользовательского элемента управления, такие как карточка контакта, я просто опустил их, потому что ни один из них не отображается и все связаны одинаково. –

+0

Является ли вашим UserControl другими окнами, которые вы заполняете выбранным человеком? Или это сетка, которая содержит все ваши лица и их информацию? – Belterius

+0

Я отредактировал свой ответ, чтобы он мог соответствовать столько поля, сколько вы хотите – Belterius