Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF update binding to element in an array

Tags:

c#

binding

wpf

I've searched my little heart out and its entirely possible that I'm missing something critical and obvious.

I have a BitArray and a series of checkboxes that are bound to elements in the array, like so:

<CheckBox IsChecked="{Binding Permissions[0]}" />
<CheckBox IsChecked="{Binding Permissions[1]}" />
...
<CheckBox IsChecked="{Binding Permissions[5]}" />

They get their values from that property correctly, but changing the checkboxes doesn't seem to trigger that property's setter.

I tried a really simple example with a single TextBox bound to an element of a string array.

class TestArray
{
    private string[] _nameArray = new string[3];

    public TestArray()
    {
        _nameArray[1] = "test name";
    }

    public string[] NameArray
    {
        get { return _nameArray; }
        set { _nameArray = value; }
    }
}

Here's the UI element:

<TextBox Text="{Binding NameArray[1], UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />

Again, this TextBox gets the name from the binding just fine, but doesn't hit the setter if I change it.

This could totally be a bonehead question and may stem from a serious lack of understanding so thanks for your patience!

like image 464
statikuz Avatar asked Aug 24 '11 18:08

statikuz


4 Answers

I've never tried this approach before but I don't think this will work. Because the property you are waiting to see the setter fire is not the property bound. NameArray is not the same as NameArray[i].

I would suggest looking into the ObservableCollection and templating to achieve multiple checkboxes. For example you could create a horizontal listbox of checkboxes that bind to an ObservableCollection.

like image 109
Josh Avatar answered Nov 20 '22 05:11

Josh


You don't end up in the setter because you don't change the value for NameArray, you change the value for a specific index in the array, e.g NameArray[1]. So the binding works but you won't end up in the setter.

A better approach is to use an ObservableCollection and bind it to an ItemsControl

like image 29
Fredrik Hedblad Avatar answered Nov 20 '22 06:11

Fredrik Hedblad


Again, this TextBox gets the name from the binding just fine, but doesn't hit the setter if I change it.

It doesn't need to call the setter: the binding doesn't replace the array, it simply replaces an element of the array. If you check the values in the array, you will see that they reflect the changes.

It also works fine with a BitArray (I just tried with both an array and a BitArray).

However, arrays (and BitArray) don't implement INotifyPropertyChanged or INotifyCollectionChanged, so if there are other bindings to the values in the array, they won't be refreshed automatically. You will need a wrapper that implements these interfaces (ObservableCollection<T> for instance)

like image 3
Thomas Levesque Avatar answered Nov 20 '22 06:11

Thomas Levesque


You will not be able to set individual array elements using element-index binding. You will need to split the collection up and set up individual properties:

class TestArray : INotifyPropertyChanged
{
    private string[] _nameArray = new string[3];

    public TestArray()
    {
        _nameArray[1] = "test name";
    }

    public string Name
    {
        get { return _nameArray[0]; }
        set { 
                _nameArray[0] = value; 
                NotifyPropertyChanged("Name"); 
            }
    }
}

You will need to use INotifyPropertyChanged as per MSDN (http://msdn.microsoft.com/en-us/library/ms743695.aspx).

like image 1
Hasanain Avatar answered Nov 20 '22 04:11

Hasanain