WPF无法在DataContent中显示模板

时间:2018-12-07 19:02:44

标签: c# wpf mvvm

我是WPF的新手,我很确定更有经验的WPF编码人员将能够在几秒钟内发现我的问题。

我试图通过将其声明为模板来在DataContent内部显示UserControl,但是我得到的却是:

enter image description here

这是我代码的相关部分:

                            <ContentControl Grid.Column="0" Grid.Row="7" Grid.ColumnSpan="3" >
                             <DataTemplate  DataType="{x:Type ViewModels:anotherViewViewModel}">
                                  <Views:anotherView Content="{Binding}"/>
                             </DataTemplate>
                           </ContentControl>

视图为:

<UserControl x:Class="materialDesignTesting.Views.anotherView"
         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:materialDesignTesting.Views"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
  <Grid Background="Aqua">

  </Grid>
</UserControl>

,模型视图为:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace materialDesignTesting.ViewModels
{
    class anotherViewViewModel
    {
    }
}

2 个答案:

答案 0 :(得分:2)

<ContentControl Grid.Column="0" Grid.Row="7" Grid.ColumnSpan="3" >
    <DataTemplate  DataType="{x:Type ViewModels:anotherViewViewModel}">
          <Views:anotherView Content="{Binding}"/>
    </DataTemplate>
</ContentControl>

正在将DataTemplate设置为内容控件的实际内容。您需要ContentTemplate属性(或设置资源):

<ContentControl Grid.Column="0" Grid.Row="7" Grid.ColumnSpan="3" >
    <ContentControl.ContentTemplate>
    <DataTemplate  DataType="{x:Type ViewModels:anotherViewViewModel}">
          <Views:anotherView Content="{Binding}"/>
    </DataTemplate>
    </ContentControl.ContentTemplate>
</ContentControl>

仅当Content的{​​{1}}属性设置为ContentControl的实例时,这才起作用。由于它没有绑定或该代码中的任何内容,我猜它仍然为null,因此不会实例化您的视图。

可以就像@Silvermind所建议的那样直接使用anotherViewModel,但是我怀疑您要进行某种动态切换。如果是这种情况,您想坚持使用当前的方法,只需给Views:anotherView展示一下即可!

相关地,除非ContentControl也是 一个anotherView,否则它可能没有ContentControl属性,因此设置/绑定是毫无意义的。 ContentanotherView的实例作为DataContext来使用,因为它位于数据模板中,而无需其他代码。

答案 1 :(得分:1)

通常,您将定义一个模板,例如:

   <DataTemplate DataType="{x:Type local:FooVM}">
       <local:FooUserControl/>
   </DataTemplate>

这在合并在app.xaml中的资源字典中。 然后绑定

<ContentControl Content="{Binding ContentProperty}"/>

在viewmodel中是数据上下文,ContentProperty设置为Viewmodel的实例,例如FooVM,以便导航到foo。 导航时,最好将ContentProperty设置为null,然后再设置新的虚拟机,除非您希望在用户导航到同一视图时保留视图状态。

无论如何,当您执行此操作时,从该模板生成的用户控件FooUserControl就会将其内容(您的vm)作为其数据上下文。

这是一个简化的示例:

public class MainWindowViewModel : INotifyPropertyChanged
{
    private object currentViewModel;

    public object CurrentViewModel
    {
        get { return currentViewModel; }
        set { currentViewModel = value; RaisePropertyChanged(); }
    }
    private RelayCommand<Type> navigateCommand;
    public RelayCommand<Type> NavigateCommand
    {
        get
        {
            return navigateCommand
              ?? (navigateCommand = new RelayCommand<Type>(
                vmType =>
                {
                    CurrentViewModel = null;
                    CurrentViewModel = Activator.CreateInstance(vmType);
                }));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

视图:

<Window x:Class="wpf_Navigation_ViewModelFirst.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:wpf_Navigation_ViewModelFirst"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <DataTemplate DataType="{x:Type local:LoginViewModel}">
        <local:LoginUC/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:UserViewModel}">
        <local:UserUC/>
    </DataTemplate>
</Window.Resources>
<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <StackPanel>
        <Button Content="Login Page"
                Command="{Binding NavigateCommand}"
                CommandParameter="{x:Type local:LoginViewModel}"
                />
        <Button Content="User Page"
                Command="{Binding NavigateCommand}"
                CommandParameter="{x:Type local:UserViewModel}"
                />
    </StackPanel>
    <ContentControl Grid.Column="1"
                    Content="{Binding CurrentViewModel}"
                    />
</Grid>