제 동료와 필자는 예상대로 ViewModel 컬렉션을 얻을 수없는 이유에 대해 필사적으로 노력했습니다. 우리는이 문제를 보여주는 아주 간단한 예제를 만들었습니다.ViewModels 컬렉션에 대한 WPF 바인딩이 예상대로 표시되지 않습니다.
기본적으로 이름과 친구 목록 (StupidPerson의 이름)이있는 StupidPerson 클래스가 있습니다. MainViewModel에서 우리는 루트 StupidPerson을 만들고 그의 친구들에게 4 명의 다른 StupidPerson 's를 추가합니다. MainWindow는 단순히 StupidPersonViewModel을 사용하여 StupidPerson 소스를 표시합니다.
StupidPersonViewModel에는 모든 종소리와 휘파람이 있으며 StupidPersonView 뒤에있는 코드는 DependencyProperty를 구현합니다. StupidPersonView는 ItemsControl의 ItemsSource를 StupidPersonViewModel의 StupidFriends 속성에 바인딩합니다.
우리는 모든 다른 가능성을 시도하기 위해 확실히 복잡하게 만들었습니다. 아래의 XAML에서 볼 수있는 것은 "Name : Fred"다음에 "Friends :"다음에 네 개의 "Name : XXXX"및 빈 "Friends :"목록이옵니다. 그러나, 내가 얻는 것은 4 명의 빈 StupidPerson 's이다.
ItemsSource에 바인딩 된 MainViewModel에서 만든 StupidPersonViewModel을 사용하는 대신 XAML 마법이 네 개의 빈 StupidPersonViewModel을 새로 작성하여 렌더링 할 항목에 사용하고 있습니다. 4 개의 빈 ViewModel 만 렌더링하기 때문에 분명히 내가 만든 목록에 바인딩됩니다.
전적으로 배플.
<UserControl x:Class="StupidXaml.StupidPersonView"
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:StupidXaml"
mc:Ignorable="d"
d:DesignHeight="300"
Background="White" Width="509.016">
<UserControl.DataContext>
<local:StupidPersonViewModel />
</UserControl.DataContext>
<StackPanel>
<Label Content="{Binding Name}" />
<Label Content="Friends:" />
<ItemsControl Margin="10,0,0,0" ItemsSource="{Binding StupidFriends}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:StupidPersonView />
</DataTemplate>
<!--<DataTemplate DataType="local:StupidPersonViewModel">
<StackPanel Orientation="Horizontal">
--><!-- Proves that binding is a StupidPersonViewModel --><!--
<Label Content="{Binding}"></Label>
--><!-- Both of these work! --><!--
<Label Content="{Binding Name}"></Label>
<Label Content="{Binding Person.Name}"></Label>
--><!-- But none of these work. How is this possible!? -->
<!-- DataContext binding -->
<!--<local:StupidPersonView DataContext="{Binding}" />
<local:StupidPersonView DataContext="{Binding DataContext, ElementName=item}" />-->
<!-- Dependency Property binding -->
<!--<local:StupidPersonView Person="{Binding Person}" />
<local:StupidPersonView Person="{Binding DataContext.Person, ElementName=item}" />
<local:StupidPersonView Person="{Binding DataContext.Person, ElementName=item, BindsDirectlyToSource=True}" x:Name="self" />--><!--
</StackPanel>
</DataTemplate>-->
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
표시이 : simplest attempt
이 XAML
<UserControl x:Class="StupidXaml.StupidPersonView"
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:StupidXaml"
mc:Ignorable="d"
d:DesignHeight="300"
Background="White" Width="509.016">
<UserControl.DataContext>
<local:StupidPersonViewModel />
</UserControl.DataContext>
<StackPanel>
<Label Content="{Binding Name}" />
<Label Content="Friends:" />
<ItemsControl Margin="10,0,0,0" ItemsSource="{Binding StupidFriends}">
<ItemsControl.ItemTemplate>
<!--<DataTemplate>
<local:StupidPersonView />
</DataTemplate>-->
<DataTemplate DataType="local:StupidPersonViewModel">
<StackPanel Orientation="Horizontal">
<!--Proves that binding is a StupidPersonViewModel-->
<Label Content="{Binding}"></Label>
<!--Both of these work!-->
<Label Content="{Binding Name}"></Label>
<Label Content="{Binding Person.Name}"></Label>
<!--But none of these work. How is this possible!?-->
<!--DataContext binding-->
<local:StupidPersonView DataContext="{Binding}" />
<local:StupidPersonView DataContext="{Binding DataContext, ElementName=item}" />
<!--Dependency Property binding-->
<local:StupidPersonView Person="{Binding Person}" />
<local:StupidPersonView Person="{Binding DataContext.Person, ElementName=item}" />
<local:StupidPersonView Person="{Binding DataContext.Person, ElementName=item, BindsDirectlyToSource=True}" x:Name="self" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
표시이 : all other attempts
0123을 는public class MainViewModel
{
public StupidPersonViewModel Source { get; set; }
public MainViewModel()
{
Source = new StupidPersonViewModel { Person = new StupidPerson { Name = "Fred" } };
Source.Person.StupidFriends.Add(new StupidPerson { Name = "Bob" });
Source.Person.StupidFriends.Add(new StupidPerson { Name = "Greg" });
Source.Person.StupidFriends.Add(new StupidPerson { Name = "Frank" });
Source.Person.StupidFriends.Add(new StupidPerson { Name = "Tommy" });
}
}
public class StupidPersonViewModel : INotifyPropertyChanged
{
[CanBeNull]
public string Name => $"Name: {this.Person?.Name}";
private StupidPerson person;
[CanBeNull]
public StupidPerson Person
{
get { return this.person; }
set
{
this.person = value;
this.RaisePropertyChanged(nameof(this.Person));
this.StupidFriends = new ObservableCollection<StupidPersonViewModel>();
foreach (var friend in value.StupidFriends)
{
this.StupidFriends.Add(new StupidPersonViewModel { Person = friend });
}
this.RaisePropertyChanged(nameof(this.Name));
this.RaisePropertyChanged(nameof(this.StupidFriends));
}
}
private void RaisePropertyChanged(string property)
{
this.OnPropertyChanged(property);
}
private ObservableCollection<StupidPersonViewModel> stupidFriends;
public ObservableCollection<StupidPersonViewModel> StupidFriends
{
get { return this.stupidFriends; }
set
{
this.stupidFriends = value;
this.RaisePropertyChanged(nameof(this.StupidFriends));
}
}
//public StupidPersonViewModel()
//{
//}
//public StupidPersonViewModel(StupidPerson person)
//{
// this.Person = person;
//}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
는
먼저 StupidPerson Fred와 Fred의 친구를 만든 다음 ViewModel을 만들고 StupidPersonViewModel의 Person 설정자에 논리가있는 상태에서 Person 속성을 할당하여 StupidFriends 목록에서 ViewModels을 만들어야합니까? –