Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UWP Data-Binding not working with ViewModel

Fairly new to UWP and MVVM I came across a problem which might seem obvious to many of you.

In my project I have 3 folders named Views, ViewModels and Models which include some files as seen in the image bellow:

Can't upload image yet (reputation):

https://i.sstatic.net/YcKus.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.

This is a sample of my 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;
        }
    }
}

This is my 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");
                }
            }
        }
    }
}

Here is an example of 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}">

Here is my 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!

Please if you need clarifications for my question just write a comment. Thank you!

like image 794
KonKarapas Avatar asked Apr 23 '26 19:04

KonKarapas


1 Answers

I am trying to implement MVVM.

And you're not getting it right yet. Forget about the Bindings for a moment, let's focus on the architecture.

Going down the acronym, you need

  • a Model. It supports your business logic and usually is defined by your backend (database). It should not depend on (be aware of) the Views or ViewModels. A lightweight UWP app could do without a Model layer.

  • a View. This is the XAML part that we like to keep as simple as possible, a.o. reasons because it's hardest to test.

  • a ViewModel. It's purpose is to serve the View. It should contain properties and commands the View can directly bind to. It does as much conversion and aggregation as possible to keep the View light. It usually relies on (0 or more) Models or Services.

Given this, it is not the case that you should always have 1 Model for 1 ViewModel. A ViewModel could use multiple Models, or none.

It is clear that your LoginPageModel.Login() is in the wrong place. Login() should be a method (Command) on your ViewModel.

Your story should go like this:

  1. I want a LoginView
  2. So I need to support it with a LoginViewModel, implementing INPC
  3. The ViewModel probably needs to use a LoginService or a UserModel. But it would only need a Model instance after a successful login. A LoginModel doesn't sound right.

Have a look at Template10 to get started with View, ViewModel and a thread-safe BindableBase.

You could also look a the picture over here for a full (over the top maybe) layout of MVVM.

like image 165
Henk Holterman Avatar answered Apr 26 '26 16:04

Henk Holterman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!