10101010
10101010

Reputation: 635

Unable to populate DataGrid

I am trying to build a datagrid where columns are generated dynamically (this works fine) but I am unable to create bindings for the columns which update automatically (something like INotifyPropertyChanged).

Creating columns dynamically and want to use dictionary elements for binding which can be modified/added dynamically. No errors seen in debug output of visual studio.

I think I am really missing something minor here.

clicking button does not populate the second column

clicking button does not populate anything

ViewModel:

class DataGridAttachedPropertyViewModel {


    public ObservableCollection<DataGridColumn> ColumnCollection { get; set; }
    public ObservableCollection<AttachedPropertyEmployee> SomEmployees { get; set; }

    public ICommand myCommand { get; set; }
    public DataGridAttachedPropertyViewModel() {

        this.ColumnCollection = new ObservableCollection<DataGridColumn>();


        DataGridTextColumn tc = new DataGridTextColumn();
        tc.Header = "Sample Column";
        // tc.Binding = new Binding("name");
        Binding forCurrent =  new Binding("SimpleDict[f]");
        forCurrent.Mode = BindingMode.TwoWay;
        tc.Binding = forCurrent;

        DataGridTextColumn tt = new DataGridTextColumn();
        tt.Header = "Column x";
        // tc.Binding = new Binding("name");
        Binding forTheCurrent = new Binding("SimpleDict[x]");
        forTheCurrent.Mode = BindingMode.TwoWay;

        tt.Binding = forTheCurrent;

        myCommand = new DelegateCommand(ButtonBase_OnClick);

        this.ColumnCollection.Add(tc);
        this.SomEmployees = new ObservableCollection<AttachedPropertyEmployee>();
        this.SomEmployees.Add(new AttachedPropertyEmployee("Rajat","Norwalk"));

        this.SomEmployees.Add(new AttachedPropertyEmployee("Matthew", "Norwalk"));
    }

    public void ButtonBase_OnClick() {
        foreach (var VARIABLE in SomEmployees) {
            VARIABLE.SimpleDict["x"] = "x";
        }
    }

}

AttachedPropertyEmployee.cs

  public class AttachedPropertyEmployee : INotifyPropertyChanged {

    private Dictionary<string, string> dict;

    public Dictionary<string, string> SimpleDict {
        get { return this.dict; }
        set
        {
            if (this.dict != value) {
                this.dict = value;
                this.NotifyPropertyChanged("SimpleDict");
            }
        }
    }

    public AttachedPropertyEmployee(string Name, string Address) {
        this.SimpleDict = new Dictionary<string, string>();
        SimpleDict["f"] ="b";
        this.name = Name;
        this.address = Address;
    }

    public string name;
    public string address { get; set; }


    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propName) {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
}

XAML:

<Window x:Class="LearnInteractivity.LearnDataGridAttachedProperty"
    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:LearnInteractivity"
    mc:Ignorable="d"
    Title="LearnDataGridAttachedProperty" Height="300" Width="300">

<!--
Put a datargrid and an attached property and update columns dynamincally. 

-->


<StackPanel>

    <DataGrid 
 local:DataGridColumnsBehavior.BindableColumns="{Binding ColumnCollection}"
        x:Name="dgg"
        AutoGenerateColumns="False" 
        ItemsSource="{Binding SomEmployees}"></DataGrid>
    <Button Content="Populate" Command="{Binding myCommand}"></Button>

</StackPanel>

Upvotes: 2

Views: 93

Answers (1)

I see two problems here.

The first is that Dictionary<TKey,TValue> doesn't implement INotifyCollectionChanged, so when you change values in it, no event is raised and the UI never knows about it. You could look for an ObservableDictionary<K,V> and use that (IIRC there are a few implementations around), or you can do it the quick and dirty way:

public void ButtonBase_OnClick() {
    foreach (var VARIABLE in SomEmployees) {
        VARIABLE.SimpleDict["x"] = "x";
        VARIABLE.NotifyPropertyChanged("SimpleDict");
    }
}

That will notify the grid that SimpleDict has changed.

The second problem is that in the DataGridAttachedPropertyViewModel constructor, you forgot to add tt to ColumnCollection.

    this.ColumnCollection.Add(tc);
    this.ColumnCollection.Add(tt);

More thoughts:

I would be more comfortable adding something like this to AttachedPropertyEmployee:

public void SetColumValue(string key, string value) {
    SimpleDict[key] = value;
    NotifyPropertyChanged("SimpleDict");
}

And use that in your loop instead:

public void ButtonBase_OnClick() {
    foreach (var VARIABLE in SomEmployees) {
        VARIABLE.SetColumnValue("x", "x");
    }
}

Incidentally, I'd change SimpleDict to Dictionary<String, Object> so you can support more types than just string, and leave formatting to the UI. And I might consider exposing a ReadOnlyDictionary<K,V> in the SimpleDict property, with the writable dictionary a private field -- so callers would have no choice but to use SetColumnValue(k,v) to set the column values.

Upvotes: 1

Related Questions