使用ContentControl在WPF中显示视图无法正常工作。

4

我目前正在独自完成一个小项目,以更好地学习WPF,我问自己的问题是,如果我想遵循MVVM模式,不同视图之间的导航将如何工作。

我偶然发现了这个问题回答了我的问题,但不幸的是它似乎不起作用。与其显示我的视图,只显示关联的ViewModel的名称空间。例如,我看到的是一个白色屏幕,上面写着“JollyFinance.ViewModels.LoginViewModel”,而不是看到我的LoginView。

下面是我的MainWindow.xaml代码:

<Window.Resources>
    <!-- Different pages -->
     <DataTemplate x:Key="LoginView" DataType="vm:LoginViewModel">
        <views:LoginView />
    </DataTemplate>
</Window.Resources>

<Window.DataContext>
    <vm:MainViewModel/>
</Window.DataContext>

<Grid>
    <ContentControl Content="{Binding CurrentViewModel}"/>
</Grid>

这是我的MainViewModel.cs:

public class MainViewModel : BindableObject
{
    private ViewModelNavigationBase _currentViewModel;

    public MainViewModel()
    {
        CurrentViewModel = new LoginViewModel();
    }

    public ViewModelNavigationBase CurrentViewModel
    {
        get { return _currentViewModel; }
        set
        {
            if (_currentViewModel != value)
            {
                _currentViewModel = value;
                RaisePropertyChanged();
            }
        }
    }
}

我的 LoginViewModel.cs 文件:

    public LoginViewModel()
    {
        LoginCommand = new RelayCommand(Login);
        NavigateCommand = new RelayCommand(Login);
    }

    private void Login(object param)
    {
        Popup codePopup = new Popup();
        TextBlock popupText = new TextBlock();
        popupText.Text = "Test";
        popupText.Background = Brushes.LightBlue;
        popupText.Foreground = Brushes.Blue;
        codePopup.Child = popupText;
    }

    public String Username { get; set; }

    public String Password { get; set; }

    public ICommand LoginCommand { get; set; }
}

我的LoginView.xaml文件是由几个按钮和文本块组成的UserControl。BindableObject只是我使用的一个实现INotifyProperty接口的抽象类。ViewModelNavigationBase是所有我的视图模型将继承的类;目前它不包含任何东西。
该如何解决这个问题,以便显示我的视图而不是关联视图模型的字符串表示?
2个回答

11

WPF不支持使用字符串作为类型标识符的隐式数据模板。

您需要使用x:Type标记扩展来指定您的视图模型类型:

<DataTemplate DataType="{x:Type vm:LoginViewModel}">
    <views:LoginView />
</DataTemplate>

奇怪,使用x:Type应该可以工作。看起来WPF无法找到您的DataTemplate。<ContentControl Content="{Binding CurrentViewModel}"/><DataTemplate DataType="vm:LoginViewModel">是否在同一个文件中定义?您可以尝试显式指定DataTemplate吗?因此,请尝试更改您的<DataTemplate x:Key="login">和内容控件:<ContentControl ContentTemplate="{StaticResource login}" ...以查看模板是否从您的内容控件“可见”... - nemesv
是的,它们都在MainWindow.xaml中。我已经尝试按照您描述的方式显式指定DataTemplate到ContentControl,但问题仍然存在。唯一的区别是,我看到的不再是“JollyFinance.ViewModels.LoginViewModel”,而是“System.Windows.DataTemplate”。 - Choub890
1
你没有正确应用ContentTemplate。完整的代码是这样的<ContentControl ContentTemplate="{StaticResource login}" Content="{Binding CurrentViewModel}"/>我猜你尝试过:<ContentControl Content="{StaticResource login}"/>这就是为什么你得到了“System.Windows.DataTemplate”的原因。除此之外,我无法在空项目中重现此问题。在那里,DataType="{x:Type vm:LoginViewModel}"可以解决问题。 - nemesv
1
不,这不是解决方案,这只是一个测试,以找出可能存在的问题。使用此 ContentTemplate="{StaticResource login}",您将失去动态替换 CurrentViewModel 并使用不同视图的能力。因此,这还不是解决方案。在 WPF 中没有任何变化,因此链接的文章也应该有效,我的关于 DataType="{x:Type vm:LoginViewModel}" 的答案也是如此... - nemesv
1
ContentControl应该使用DataTemplate,如果找到一个的话。因此,显示字符串并不正常。请检查这个简单的例子,在这个例子中,您的代码可以使用我的修复:https://www.dropbox.com/s/vgzww3vn1ankg4r/WpfApplication1.zip?dl=0 <DataTemplate DataType="{x:Type vm:LoginViewModel}"> - nemesv
显示剩余5条评论

9
我终于找到了问题所在。由于某种原因,当您在DataTemplate上声明x:Key时,它会使ContentControl Content显示为字符串。我已经删除了DataTemplate的x:Key,现在一切都正常工作了。我还必须应用nemesv的答案才能使其正常工作。
之前:
<DataTemplate x:Key="LoginView" DataType="vm:LoginViewModel">

解决后:

<DataTemplate DataType="{x:Type vm:LoginViewModel}">

3
如果使用了x:Key,就无法同时使用DataType,因为x:Key会覆盖DataType的隐性设置。因此,如果你使用了x:Key,就必须在模板中使用ContentTemplate="{StaticResource LoginView}" - nemesv
是的,我已经注意到这是你的代码和我的唯一区别,并尝试删除它,结果成功了。再次感谢你的耐心和帮助! - Choub890
我遇到了相同的问题: - Luke
如果您想通过键引用它并且仍然将其作为类型的默认DataTemplate工作,那么您可以删除Key = ...,创建第二个DataTemplate,并使用BasedOn = {x:Type ...}和相同的DataType。 - Chris Bordeman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接