Wpf Mvvm Passing a string from ViewModel to a views label or textblock

Anja 426 Reputation points
2021-04-11T16:02:40.227+00:00

In my ViewModel I have made a property name MessageError, and in the View I make a binding. But somehow the message doesn't get to the view - leave the label/textblock blank.

No matter what I'm trying I cann't see where the problem is. When "run to cursor" I try to step into everything, but doesn't show me any kind of error. It set the message, but doesn't shop up in the view.

I hope one of you can see, where I make an error?

Best regards
Simsen :-)

My viewModel property:

private string _messageError;
        public string MessageError
        {
            get => _messageError;
            set
            {
                _messageError = value;
                OnPropertyChanged("MessageError");
            }
        }

In the viewmodel I have a method witch set the text (no errors when run to cursor)

    public void SaveChangesNew()
            {
                string name = CategoryName;
                bool global = CategoryIsGlobal;
                bool obsolete = CategoryIsObsolete;
                int projectId = ProjectId;
                MessageError = "Den er ikke gemt";
            }

And the view look likes this

<TextBlock x:Name="TblMessage" Text="{Binding MessageError, Mode=TwoWay}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" />
                <!--<Label x:Name="LblMessage" Content="{Binding Path=MessageError}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" />-->
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,705 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,565 questions
0 comments No comments
{count} votes

Accepted answer
  1. Peter Fleischer (former MVP) 19,306 Reputation points
    2021-04-11T18:06:44.61+00:00

    Hi Anja,
    your code works properly. Please, check assignment of DataContext and Immediate Window. Following demo with yours code works properly.

    XAML:

    <Window x:Class="WpfApp1.Window041"
            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:WpfApp041"
            mc:Ignorable="d"
            Title="Window041" Height="450" Width="800">
      <Window.DataContext>
        <local:ViewModel/>
      </Window.DataContext>
      <StackPanel>
        <Button Content="Click to check" Command="{Binding}"/>
        <TextBlock x:Name="TblMessage" Text="{Binding MessageError}"/>
      </StackPanel>
    </Window>
    

    And ViewModel:

    using System;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Input;
    
    namespace WpfApp041
    {
      public class ViewModel : ICommand, INotifyPropertyChanged
      {
        private string _messageError;
        public string MessageError
        {
          get => _messageError;
          set
          {
            _messageError = value;
            OnPropertyChanged("MessageError");
          }
        }
        public void SaveChangesNew()
        {
          //string name = CategoryName;
          //bool global = CategoryIsGlobal;
          //bool obsolete = CategoryIsObsolete;
          //int projectId = ProjectId;
          MessageError = "Den er ikke gemt";
        }
        public void Execute(object parameter) => SaveChangesNew();
    
        public event EventHandler CanExecuteChanged;
        public bool CanExecute(object parameter) => true;
    
        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName) =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        #endregion
      }
    }
    

1 additional answer

Sort by: Most helpful
  1. Anja 426 Reputation points
    2021-04-12T09:35:11.533+00:00

    I have now looked at 3 videos and can't get the Immediate Window. to show anything. Most of the time, it says that I can't make anything on a library.

    But I have tried a lot of difference things and think that it could have something to do with the MyICommand I have made (again from a video) for the Command purpose.

    Here I don't use the CanExecute command because I do not want it to grey out the buttons. So maybe it has with that to do?

    My MyICommand

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows.Input;
    
    namespace ViewModel
    {
        public class MyICommand : ICommand
        {
            readonly Action _TargetExecuteMethod;
            readonly Func<bool> _TargetCanExecuteMethod;
    
            public MyICommand(Action executeMethod)
            {
                _TargetExecuteMethod = executeMethod;
            }
    
            public MyICommand(Action executeMethod, Func<bool> canExecuteMethod)
            {
                _TargetExecuteMethod = executeMethod;
                _TargetCanExecuteMethod = canExecuteMethod;
            }
    
            public void RaiseCanExecuteChanged()
            {
                CanExecuteChanged(this, EventArgs.Empty);
            }
    
            bool ICommand.CanExecute(object parameter)
            {
    
                if (_TargetCanExecuteMethod != null)
                {
                    return _TargetCanExecuteMethod();
                }
    
                if (_TargetExecuteMethod != null)
                {
                    return true;
                }
    
                return false;
            }
    
            // Beware - should use weak references if command instance lifetime 
            // is longer than lifetime of UI objects that get hooked up to command
    
            // Prism commands solve this in their implementation 
            public event EventHandler CanExecuteChanged = delegate { };
    
            void ICommand.Execute(object parameter)
            {
                _TargetExecuteMethod?.Invoke();
            }
        }
    }
    

    In my ViewModel I use it this way:

    public CategoryViewModel()
            {
                LoadCategories();
                LoadProjects();            
                CmdSave = new MyICommand(SaveChanges);
                CmdSaveNew = new MyICommand(SaveChangesNew);
            }
    

    and

    public MyICommand CmdSaveNew { get; set; }
            public void SaveChangesNew()
            {
                if (CategoryName != null)
                {
                    string name = CategoryName;
                    bool global = CategoryIsGlobal;
                    bool obsolete = CategoryIsObsolete;
                    int projectId = ProjectId;
                    MessageError = "This message I want to see in the view";
    
                    string test = "hej";
                }
                else
                {
                    MessageError = string.Empty;
                }
            }
    

    Do I do it wrong this way?

    Best regards
    Simsen :-)