UWP 数据绑定不适用于 ViewModel

UWP Data-Binding not working with ViewModel

我是 UWP 和 MVVM 的新手,我遇到了一个对你们中的许多人来说似乎显而易见的问题。

在我的项目中,我有 3 个名为 ViewsViewModelsModels 的文件夹,其中包含一些文件,如下图所示:

Can't upload image yet (reputation):

http://i.imgur.com/42f5KeT.png

The problem: I am trying to implement MVVM. I have searched hours for articles and videos but it seems I am always missing something. I have some bindings in the LoginPage.xaml which I then modify in a class inside Models/LoginPageModel.cs. I have an INotifyPropertyChanged class in my LoginPageViewModel.cs where every time a property changes in my LoginPageModel.cs I want the INotifyPropertyChanged class to trigger which will then change the property in the LoginPage.xaml View. Below I have the content of those files.

这是我的 LoginPageModel.cs 代码示例:

using System;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace App_Name.Models
{
    class LoginPageModel
    {
        private NotifyChanges notify;

        public async void LogIn()
        {
            if (something is true)
                notify.LoginUIVisibility = Visibility.Visible;
        }
    }
}

这是我的LoginPageViewModel.cs:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using Windows.UI.Xaml;

namespace App_Name.ViewModels
{
    public class NotifyChanges : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private Visibility loginUIVisibility = Visibility.Collapsed;

        public Visibility LoginUIVisibility
        {
            get
            {
                return loginUIVisibility;
            }

            set
            {
                if (value != loginUIVisibility)
                {
                    loginUIVisibility = value;
                    NotifyPropertyChanged("LoginUIVisibility");
                }
            }
        }
    }
}

下面是LoginPage.xaml的例子:

<Page
    x:Class="App_Name.LoginPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App_Name"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="using:App_Name.ViewModels"
    mc:Ignorable="d">

    <Page.DataContext>
        <vm:NotifyChanges/>
    </Page.DataContext>

    <StackPanel Visibility="{Binding LoginUIVisibility}">

这是我的 LoginPage.xaml.cs:

namespace App_Name
{
    public sealed partial class LoginPage : Page
    {
        private LoginPageModel login;
        public LoginPage()
        {
            InitializeComponent();
            login.LogIn();
        }
    }
}

I don't know why this is not working. Bindings used not to work, but now at runtime it gives me an unhandled exception and I think it has to do with not assigning any value to the private NotifyChanges notify and private LoginPageModel login objects, but I don't know what. Thanks everyone for your time in advance!

如果您需要澄清我的问题,请发表评论。谢谢!

And here is the call for change in the main class:

NotifyChanges notifyChanges = new NotifyChanges();

notifyChanges.LoginUIVisibility = Visibility.Visible;

您已通过添加 <vm:NotifyChanges/>XAML 文件中实例化 notifyChanges。并使用 <StackPanel Visibility="{Binding LoginUIVisibility}"> 添加到 StackPanel 的绑定。但是你创建了一个新的notifyChanges,你并没有将新的notifyChanges绑定到StackPanel。所以它不会工作。您可以像下面的代码一样初始化 viewModel

主页

private LoginViewModel viewModel;

public MainPage()
 {
     this.InitializeComponent();
     viewModel = this.DataContext as LoginViewModel;
 }

 private void showDetail_Click(object sender, RoutedEventArgs e)
 {
     viewModel.LoginUIVisibility = Visibility.Visible;
 }
 

MainPage.xaml

<Page.DataContext>
    <vm:LoginViewModel />
</Page.DataContext>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Button x:Name="loginButon" Content="Login" Visibility="{Binding LoginUIVisibility}" />
    <Button x:Name="showDetail" Content="Show" Click="showDetail_Click" />
</StackPanel>

I am trying to implement MVVM.

而且你还没有做对。暂时忘掉绑定,让我们关注架构。

按照首字母缩略词,你需要

  • 一个模型。它支持您的业务逻辑,通常由您的后端(数据库)定义。它不应该依赖于(注意)视图或视图模型。轻量级 UWP 应用程序可以在没有模型层的情况下运行。

  • 一个视图。这是我们希望尽可能简单的 XAML 部分,a.o。原因是因为它最难测试。

  • 一个视图模型。它的目的是为视图服务。它应该包含视图可以直接绑定到的属性和命令。它尽可能多地进行转换和聚合以保持 View 轻盈。它通常依赖于(0 个或更多)模型或服务。

鉴于此,您不应该总是为 1 个 ViewModel 使用 1 个模型。一个 ViewModel 可以使用多个模型,或者 none。

很明显你的LoginPageModel.Login()放错地方了。 Login() 应该是您的 ViewModel 上的一个方法(命令)。

你的故事应该是这样的:

  1. 我想要一个登录视图
  2. 所以我需要用 LoginViewModel 来支持它,实现 INPC
  3. ViewModel 可能需要使用 LoginService 或 UserModel。但是在成功登录后它只需要一个模型实例。 LoginModel 听起来不对。

查看 Template10 以开始使用 View、ViewModel 和线程安全的 BindableBase。

您还可以查看图片 以了解 MVVM 的完整(可能在顶部)布局。