0

I'm not sure what I am doing wrong but I am trying to bind a class properties into an ObservableCollection so I can display added values to the rows in the DataGrid. Here is my code.

XAML:

enter image description here

C#:

 namespace WpfApp1
 {
    public partial class MainWindow : Window
    {
        ObservableCollection<StatusLog> statusLog = new ObservableCollection<StatusLog>();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            statusLog.Add(new StatusLog { TimeStamp = DateTime.Now.ToString(), Title="Sample Title", Message="Sample Message" }); 
        }
    }

    public class StatusLog : INotifyPropertyChanged
    {
        private string timeStamp;
        private string title;
        private string message;

        public string TimeStamp
        {
            get { return timeStamp; }
            set
            {
                if(timeStamp != value)
                {
                    timeStamp = value;
                    OnPropertyChanged("TimeStamp");
                }
            }
        }

        public string Title
        {
            get { return title; }
            set
            {
                if (title != value)
                {
                    title = value;
                    OnPropertyChanged("TimeStamp");
                }
            }
        }

        public string Message
        {
            get { return message; }
            set
            {
                if (message != value)
                {
                    message = value;
                    OnPropertyChanged("TimeStamp");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

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

If anyone can guide me to fix this, I would appreciate it.

Lucifer
  • 1,594
  • 2
  • 18
  • 32
redvolt
  • 68
  • 6
  • I realized I copied the OnPropertyChanged("TimeStamp"); on all three properties without changing the name. I have changed it to the appropriate name and it still doesn't work. – redvolt Jan 03 '20 at 04:46
  • Shouldn't statusLog be public? – Tanveer Badar Jan 03 '20 at 04:47
  • Yes you are right, but that still didn't make a difference in the outcome. – redvolt Jan 03 '20 at 04:49
  • Are there any warnings about binding failures when you debug the application? Check your output window. – Tanveer Badar Jan 03 '20 at 04:51
  • Just checked. 0 errors 0 warnings. – redvolt Jan 03 '20 at 04:53
  • I noticed this: Step into: Stepping over non-user code 'WpfApp1.App..ctor' Step into: Stepping over non-user code 'WpfApp1.App.InitializeComponent' – redvolt Jan 03 '20 at 04:55
  • 1
    Have you set the DataContext for the Window? – Justin CI Jan 03 '20 at 05:56
  • The solution is to bind to properties instead of fields. Fields are not supported by the binding engine. To avoid future errors due to copy & paste, typos or the renaming of properties you have to avoid string literals by using `nameof()` or `CallerMemberNameAttribute`. So the `TimeStamp` property changed invocator becomes: `OnPropertyChanged(nameof(this.TimeStamp));` when using `nameof().` Now you get compiler and Intellisense support. When using refactoreing tools like Resharper they will automatically rename the `nameof()` parameter for you too. – BionicCode Jan 03 '20 at 08:08
  • Or becomes `OnPropertyChanged()` when the event invocator's parameter is decorated with the `CallerMemberName` attribute: `protected void OnPropertyChanged([CallerMemberName] string propertyName = null) => this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));`. – BionicCode Jan 03 '20 at 08:08
  • As other comments said, you'll need to set a proper `DataContext` for the Window and convert your field `statusLog` to property. Also, please do not post code as images – Pavel Anikhouski Jan 03 '20 at 09:05

2 Answers2

3

With the following code you're creating a field:

public ObservableCollection<StatusLog> statusLog = new ObservableCollection<StatusLog>();

But you need a property for the binding to work. So you have to change your code to something like:

public ObservableCollection<StatusLog> statusLog { get; } = new ObservableCollection<StatusLog>();

I would recommend you to write the property with uppercase.

Tomtom
  • 9,087
  • 7
  • 52
  • 95
0

So I figured out the issue. I followed TomTom's post about making the field a property. I also did not have datacontext set so once I did that, it worked.

redvolt
  • 68
  • 6