我有一个ViewModel的ObservableCollection,我想绑定到包含相关子视图的ItemsControl。当我将ViewModels添加到我的集合中时,ItemsControl中会生成适当数量的子视图。但是,每个生成的视图的DataContext都为null。如果我内联我的子视图,它可以正常工作。那么,我需要做什么才能将我的子视图的DataContext设置为我的ViewModels?
这是我的父ViewModel中的相关位:
public ObservableCollection<ChildViewModel> Numbers { get; set; }
public ParentViewModel()
{
Numbers = new ObservableCollection<ChildViewModel>();
}
private void ShowNumbers()
{
foreach (var num in Enumerable.Range(0, number))
{
var childView = new ChildViewModel(number.ToString());
Numbers.Add(childView);
}
}
父视图中的相关位:
<ItemsControl ItemsSource="{Binding Numbers, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type vm:ChildViewModel}">
<v:ChildView />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
儿童观点:
<UserControl x:Class="TestWpfApp.Views.ChildView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid>
<Label Content="{Binding NumberString}" Width="30" Height="30" BorderThickness="1" BorderBrush="Black" HorizontalAlignment="Center"/>
</Grid>
</UserControl>
Child ViewModel:
public class ChildViewModel : BindableBase
{
private string numberString;
public string NumberString
{
get
{
return numberString;
}
set
{
SetProperty(ref numberString, value);
}
}
public ChildViewModel() { }
public ChildViewModel(string number)
{
NumberString = number;
}
}
显然,我有一些错误的配置,但我不能为我的生活找出什么。
仅供参考我正在使用棱镜库
答案 0 :(得分:2)
WPF会自动将DataContext
中的项容器元素的ItemsControl
设置为相应的项目实例,以便它可以继承到ItemTemplate
。显然,当您设置prism:ViewModelLocator.AutoWireViewModel
属性时,此机制将被禁用。
所以,只需将它从您的ChildView的XAML中删除:
<UserControl x:Class="TestWpfApp.Views.ChildView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/">
<Grid>
<Label Content="{Binding NumberString}" Width="30" Height="30"
BorderThickness="1" BorderBrush="Black" HorizontalAlignment="Center" />
</Grid>
</UserControl>
作为一般规则,UserControl永远不应该直接或通过像DataContext
之类的机制显式设置自己的AutoWireViewModel
,因为这有效地阻止了从其父控件继承DataContext
答案 1 :(得分:1)
在ItemsControl中生成适当数量的子视图。
因此可以得出结论,DataContext
已正确设置为viewModel
,但未应用DataTemplate's
。
我有同样的问题,我也在使用Prism
库。我想分享一下如何做到这一点的方式。也许对你有帮助。我用CompositeCollection
:
<强>视图模型:强>
public class MainWindowVM:ViewModelBase
{
public MainWindowVM()
{
LoadData();
}
private void LoadData()
{
ObservableCollection<Human> coll = new ObservableCollection<Human>();
for (int indexLoop = 0; indexLoop < 5; indexLoop++)
{
if (indexLoop % 2 == 0)
{
coll.Add(new Sportsman() {FirstName=indexLoop.ToString(), LastName=indexLoop.ToString()});
}
else
{
coll.Add(new Employee() { FirstName = indexLoop.ToString(), LastName = indexLoop.ToString()});
}
}
CompositeCollection compositeColl = new CompositeCollection();
compositeColl.Add(new CollectionContainer() { Collection = coll });
FooData = compositeColl;
}
private CompositeCollection fooData;
public CompositeCollection FooData
{
get { return fooData; }
set
{
fooData = value;
}
}
}
<强>型号:强>
public class Human
{
private string firstName;
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
private string lastName;
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
}
public class Sportsman:Human
{ }
public class Employee:Human
{ }
查看:强>
<Window x:Class="ItemsControlWithDataTemplates.MainWindow"
<!--The code is omitted for the brevity-->
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<vm:MainWindowVM/>
</Window.DataContext>
<Grid>
<ItemsControl ItemsSource="{Binding FooData}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type model:Employee}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
<TextBlock Text=" ( Employee"/>
<TextBlock Text="{Binding LastName}"/>
<TextBlock Text=")"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type model:Sportsman}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
<TextBlock Text=" - Sportsman "/>
<TextBlock Text="{Binding LastName}"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type model:Human}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
<TextBlock Text=" - "/>
<TextBlock Text="{Binding LastName}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
</Grid>
</Window>
实际上我在DataContext
应用程序中以下列方式设置了Prism
:
public MyUserControl(IMyViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}