DataContext not set when using View as DataTemplate in ItemsControl

自作多情 提交于 2019-12-06 04:25:02

WPF automatically sets the DataContext of an item container element in an ItemsControl to the appropriate item instance, so that it can be inherited into the ItemTemplate. Apparently this mechanism is disabled when you set the prism:ViewModelLocator.AutoWireViewModel property.

So, just remove it from your ChildView's 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>

As a general rule, a UserControl should never explicitly set its own DataContext, neither directly nor by a mechanism like AutoWireViewModel, because that effectively prevents inheriting a DataContext from its parent control.

An appropriate number of child Views are generated in the ItemsControl.
So it can be concluded that DataContext is set to your viewModel correctly, but DataTemplate's is not applied.

I have the same problem and I am also using Prism library. I would like to share about the way how it can be done. Maybe it helps to you. I've used CompositeCollection:

ViewModel:

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

}

Model:

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

View:

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

Actually I set DataContext in the following way in my Prism application:

public MyUserControl(IMyViewModel viewModel)
{
    InitializeComponent();
    DataContext = viewModel;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!