0

I am trying to bind List<bool> from MainWindow to my UserControl. MainWindow obtained list from other UserControl. I wanted to bind it to its child control and do some actions when element of the List was changed, so I wrote this piece of code:

MainWindow class:

public static readonly DependencyProperty mRowsInfoProperty =
    DependencyProperty.Register("mRowsInfo", typeof(List<bool>), typeof(MainWindow),
        new FrameworkPropertyMetadata(new List<bool>()));

public List<bool> mRowsInfo
{
    get { return (List<bool>)GetValue(mRowsInfoProperty); }
    set { SetValue(mRowsInfoProperty, value); }
}
public List<bool> RowsInfo
{
    get { return mRowsInfo; }
    set
    {
        mRowsInfo = value;
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("RowsInfo"));
    }
}

MainWindow xaml:

<local:CustomGrid isRowValid="{Binding RowsInfo, Mode=TwoWay}">
<local:ControlButtons ButtonsBacklitList="{Binding mRowsInfo, ElementName=myWindow}"/>

UserControl class:

 public static readonly DependencyProperty ButtonsBacklitListProperty =
            DependencyProperty.Register("ButtonsBacklitList", typeof(ObservableCollection<bool>), typeof(ControlButtons),
                new FrameworkPropertyMetadata(new ObservableCollection<bool>(), onBBLCallBack));

        public ObservableCollection<bool> ButtonsBacklitList
        {

            get { return (ObservableCollection<bool>)GetValue(ButtonsBacklitListProperty); }
            set { SetValue(ButtonsBacklitListProperty, value); }
        }
        private static void onBBLCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ControlButtons h = sender as ControlButtons;
            if (h != null)
            {
                h.onBBLChanged();
            }
        }
        protected virtual void onBBLChanged()
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("ButtonsBacklitList"));
            Console.WriteLine("UPDATED");
        }

And when i break at some point in code (after clicking button) ButtonsBacklitList is always null. What should i change or add to do this correctly?

Franky
  • 117
  • 1
  • 1
  • 7
  • Firstly, why would you use `INotifyPropertyChanged` together with `DependencyProperty`? Having a `List` implemented as a `DependencyProperty` would allow binding to trigger if the list is re-instantiated (or re-assigned to another list of different reference address). – Jai May 16 '16 at 02:00

1 Answers1

1

MainWindow class:

public static readonly DependencyProperty RowsInfoProperty =
    DependencyProperty.Register("RowsInfo", typeof(ObservableCollection<bool>), typeof(MainWindow),
        new FrameworkPropertyMetadata(new ObservableCollection<bool>()));

public ObservableCollection<bool> RowsInfo
{
    get { return (ObservableCollection<bool>)GetValue(RowsInfoProperty); }
    set { SetValue(RowsInfoProperty, value); }
}

MainWindow xaml:

<local:CustomGrid isRowValid="{Binding RowsInfo, Mode=TwoWay}">
<local:ControlButtons ButtonsBacklitList="{Binding RowsInfo, ElementName=myWindow}"/>

UserControl class:

public static readonly DependencyProperty ButtonsBacklitListProperty =
    DependencyProperty.Register("ButtonsBacklitList", typeof(ObservableCollection<bool>), typeof(ControlButtons),
        new FrameworkPropertyMetadata(new ObservableCollection<bool>(), onBBLCallBack));

public ObservableCollection<bool> ButtonsBacklitList
{
    get { return (ObservableCollection<bool>)GetValue(ButtonsBacklitListProperty); }
    set { SetValue(ButtonsBacklitListProperty, value); }
}

// Not sure why you want to capture changes, I hope it's not for binding
// But I'm copying it anyway
private static void onBBLCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    ControlButtons h = sender as ControlButtons;
    if (h != null)
    {
        h.onBBLChanged();
    }
}

// This looks super suspicious because all you did is to trigger INotifyPropertyChanged's handler!
// I hope somewhere in your code you actually need to manually handle this change event...
protected virtual void onBBLChanged()
{
    if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs("ButtonsBacklitList"));
    Console.WriteLine("UPDATED");
}

Firstly, I got the feeling that you are not too familiar with binding concepts. Implementing as List<bool> means that the binding will only react to changes in the whole property's reference (e.g. this.RowInfo = new List<bool>).

Secondly, not sure why you are stacking DependencyProperty with INotifyPropertyChanged. For a property to be a binding source (for a binding which receives change notifications), it just need to be either of these two. For a property to be a binding target, it must, however, be a DependencyProperty. For example, in <local:CustomGrid isRowValid="{Binding RowsInfo, Mode=TwoWay}">, isRowValid is the binding target, this must be a DependencyProperty, while RowsInfo is the binding source, and it can be either of the two.

I hope I managed to help you some.

Jai
  • 8,165
  • 2
  • 21
  • 52
  • Thank you very much for answer, it was very helpful. Truly speaking its my first project with wpf, so i need to get some practice with binding an other mechanics. I need to capture changes on collection's items, not collection itself. It was part of my problem. I read [this page](http://stackoverflow.com/questions/1427471/observablecollection-not-noticing-when-item-in-it-changes-even-with-inotifyprop), but I am not sure which answer will solve my problem – Franky May 16 '16 at 09:28
  • The initial stage is the most painful. I am also pretty new, started about 2 months ago, with no prior experience in C#, WPF nor MVVM. I was also constantly in the state of confusion then. After reading lots of articles and SO questions/answers, then trying them out, I think I am pretty familiar with binding (the MVVM way) now. – Jai May 16 '16 at 09:33