Search code examples
c#data-bindingdatacontextinotifypropertychanged

C# Binding with DataContext and INotifyPropertyChanged


What am I doing wrong?

I have a Class Model.cs that has my DataContext

I have a Button and a TextBlock next to it. I have tried binding and implementing INotifyPropertyChanged.

When the button is clicked it calls a method that uses WinForms to look for a folder location and display it in the TextBlock

but it does not update. If I debug I get the path correctly.

Any help much appreciated.

MainWindow.xaml

<Button  Name="projectLocationBtn" 
    Width="150" 
    Height="30" 
    Click="projectLocationBtn_Click">
    <StackPanel Orientation="Horizontal">
      <fa:FontAwesome Icon="FolderOpen" Margin="0 0 10 0" />
       <TextBlock Text="Select Location" />
   </StackPanel>                
</Button>

<StackPanel Orientation="Horizontal" Margin="20 0 0 0">
    <fa:FontAwesome Icon="AngleRight" Margin="0 0 10 0"/>
     <TextBlock Width="800" 
                 TextAlignment="Left" 
                  TextWrapping="NoWrap" 
                   Text="{Binding ProjectLocation}"/>
 </StackPanel>

MainWindow.xaml.cs

using M = MercuryTemplateGenerator.Model;

public MainWindow()
{
   InitializeComponent();
    DataContext = new M.Model();
}

 private void projectLocationBtn_Click(object sender, RoutedEventArgs e)
  {
     M.Model m = new M.Model();
     m.GetLocation();
 }

Model Class

using Winforms = System.Windows.Forms;

namespace MercuryTemplateGenerator.Model
{
    public class Model: INotifyPropertyChanged
    {

        string _projectLocation;
        string _projectName;

       public Model()  {}

       public string ProjectName
       {
            get {
                return _projectName; }
            set {
                _projectName = value;
                OnPropertyChanged("ProjectName");
            }
        }

        public string ProjectLocation
        {
            get {
                return _projectLocation; }
            set {
                   _projectLocation = value;
                   OnPropertyChanged("ProjectLocation");

            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string property)
        {
            PropertyChanged?.Invoke(this, new 
            PropertyChangedEventArgs(property));
        }

        public void GetLocation()
        {
            // get path to desktop
            var startPath =  
            Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            Winforms.FolderBrowserDialog folderDialog = new 
            Winforms.FolderBrowserDialog();
            folderDialog.ShowNewFolderButton = false;
            folderDialog.SelectedPath = startPath;
            Winforms.DialogResult pathResult = folderDialog.ShowDialog();

            if (pathResult == Winforms.DialogResult.OK)
            {
                _projectLocation = folderDialog.SelectedPath;
            }
        }

    }
}

Many thanks.


Solution

    1. The mistake is you have one instance of Model for dataContext of the page and have another one instance you're calling inside projectLocationBtn_Click. If a view is bounded to dataContext it means it's special instance of class lays under view and view will get new data from there. You need to call GetLocation method on the same instance of Model. For example, you can save your first model to field.

      _dataContext = new M.Model(); DataContext = _dataContext;

    And then use this instance inside handler

    private void projectLocationBtn_Click(object sender, RoutedEventArgs e)
    {
        _dataContext.GetLocation();
    }
    
    1. I can see that after all, it won't work because you don't call OnPropertyChanged("ProjectLocation"). For calling it you have to call setter of ProjectLocation property

    Replace:
    _projectLocation = folderDialog.SelectedPath; with
    ProjectLocation = folderDialog.SelectedPath;

    1. And for your info: Check how can Button's click be bound to DataContext with Binding work inside XAML file. https://www.codeproject.com/Articles/238657/How-to-use-Commands-in-WPF