Mvvm UWP数据绑定不适用于ViewModel

Mvvm UWP数据绑定不适用于ViewModel,mvvm,data-binding,uwp,inotifypropertychanged,uwp-xaml,Mvvm,Data Binding,Uwp,Inotifypropertychanged,Uwp Xaml,对于UWP和MVVM来说,我是一个相当陌生的人,我遇到了一个对你们中的许多人来说似乎很明显的问题 在我的项目中,我有3个名为视图、视图模型和模型的文件夹,其中包括一些文件,如下图所示: 尚无法上载图像(声誉): 问题: 我正在尝试实现MVVM。我已经搜索了数小时的文章和视频,但似乎我总是错过一些东西。我在LoginPage.xaml中有一些绑定,然后在Models/LoginPageModel.cs中的类中修改这些绑定。我在LoginPageViewModel.cs中有一个INotifyPro

对于UWP和MVVM来说,我是一个相当陌生的人,我遇到了一个对你们中的许多人来说似乎很明显的问题

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

尚无法上载图像(声誉):

问题: 我正在尝试实现MVVM。我已经搜索了数小时的文章和视频,但似乎我总是错过一些东西。我在
LoginPage.xaml
中有一些绑定,然后在
Models/LoginPageModel.cs
中的类中修改这些绑定。我在LoginPageViewModel.cs中有一个
INotifyPropertyChanged
类,每当我的
LoginPageModel.cs
中的属性发生更改时,我希望触发
INotifyPropertyChanged
类,然后该类将更改
LoginPage.xaml
视图中的属性。下面是这些文件的内容

这是我的
LoginPageModel.cs
code:

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;
        }
    }
}
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");
                }
            }
        }
    }
}
<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}">
namespace App_Name
{
    public sealed partial class LoginPage : Page
    {
        private LoginPageModel login;
        public LoginPage()
        {
            InitializeComponent();
            login.LogIn();
        }
    }
}
这是我的
LoginPageViewModel.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;
        }
    }
}
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");
                }
            }
        }
    }
}
<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}">
namespace App_Name
{
    public sealed partial class LoginPage : Page
    {
        private LoginPageModel login;
        public LoginPage()
        {
            InitializeComponent();
            login.LogIn();
        }
    }
}
下面是
LoginPage.xaml
的一个示例:

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;
        }
    }
}
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");
                }
            }
        }
    }
}
<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}">
namespace App_Name
{
    public sealed partial class LoginPage : Page
    {
        private LoginPageModel login;
        public LoginPage()
        {
            InitializeComponent();
            login.LogIn();
        }
    }
}
我不知道这为什么不起作用。绑定过去不起作用,但现在在运行时它给了我一个未处理的异常,我认为这与没有为
private NotifyChanges notify
private LoginPageModel login
对象分配任何值有关,但我不知道是什么。提前感谢大家抽出时间

如果你需要澄清我的问题,请写一条评论。谢谢大家!

以下是对主要课程改革的呼吁:

NotifyChanges NotifyChanges=new NotifyChanges()

notifyChanges.loginuviability=可见性.Visible

通过添加
,您已经在
XAML
文件中实例化了
notifyChanges
。并使用
向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>

我正在尝试实现MVVM

而且你还没弄对。暂时忘掉绑定吧,让我们关注一下体系结构

在首字母缩略词中,您需要

  • 模特儿。它支持您的业务逻辑,通常由后端(数据库)定义。它不应依赖(注意)视图或视图模型。轻量级UWP应用程序可以不使用模型层

  • 景色。这是我们希望尽可能简单的XAML部分,因为它最难测试

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

考虑到这一点,您不应该总是将1个模型用于1个ViewModel。ViewModel可以使用多个模型,也可以不使用任何模型

很明显,您的
LoginPageModel.Login()
位于错误的位置<代码>登录()
应该是ViewModel上的方法(命令)

你的故事应该是这样的:

  • 我想要一个登录视图
  • 所以我需要用一个LoginViewModel来支持它,实现INPC
  • ViewModel可能需要使用LoginService或UserModel。但在成功登录后,它只需要一个模型实例。LoginModel听起来不太正确 了解如何开始使用View、ViewModel和线程安全的BindableBase


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

    基本上,您正在创建新的notifyChanges对象(ViewModel的名称…),并在其中设置属性,如果is将这个类的不同实例设置为DataContext,为什么您希望UI发生变化?所以这会进入我的初始页面构造函数而不是XAML?如何在ViewModel文件中引用它?这是一种可能的方法,在Constructor(在xaml.cs文件中)中创建ViewModel的实例,保留对它的引用并将其设置为DataContext,现在,当您要处理这个被引用对象的属性时,如果所有内容都在同一个文件中,那么UI应该会发生变化。我的问题是DataContext=newnotifychanges();发生在我的XAML.cs文件中,NotifyChanges()类和修改这些属性的类位于不同的文件中。不同的文件:两个类是NotifyChanges,另一个是修改发生的地方。同样,如何在不创建新实例的情况下,将这些属性从NotifyChanges类引用到同一文件中的上述类?谢谢:)DataContext=newnotifychanges();在上面的示例中没有命名的神秘控件的constructor xaml.cs文件中,然后在不同的对象中,需要引用ViewModel(只需更改其属性)或控件(xaml.cs)实例-如果是这样,则获取其DataContext(例如,var ViewModel=sampleControl.DataContext as NotifyChanges;)并使用其属性提示:阅读MVVM中的视图优先和视图模型优先方法