我有一个UserControl,它有一个ViewModel,包含我自己的自定义类的实例,称之为Person。此ViewModel设置为控件的DataContext。我想在我的主窗口中使用此控件,该窗口在其ViewModel中具有名为People的Person类型的List。我在我的xaml中调用控件,如下所示:
<ItemsControl ItemsSource="{Binding People}">
<ItemsControl.ItemsTemplate>
<DataTemplate>
<userControls:PersonDetails />
</DataTemplate>
</ItemsControl.ItemsTemplate>
</ItemsControl>
控件中的属性以这种方式绑定。
<TextBlock Text="{Binding Person.Name}" />
当我运行时,我获得了列表中人员数量的正确控制数量,但没有填充任何详细信息。我知道我做了一些简单的错误,却无法找到它。请帮忙。
编辑:
我的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 :(得分: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
的{{1}}。
答案 1 :(得分:0)
不确定这是不是你想要做的。 如果您只希望显示人员列表中每个人的某些内容,您可以这样做:
<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>
这将绑定您列表中每个元素的Name属性上的Text,以及列表中每个Person的名称。 由于您的ItemsSource已经绑定到People,因此您的Items的绑定已经在List的每个Person上,因此您应该直接将您的属性称为{Binding Name}而不是{Binding Person.Name}