5

I have implemented the dynamic dataGrid by following this link.

I am using Converter to bind the values from ExpandoObject. The columns shows values like total units for schools.

Item      ItemCount DefaultSchool School1  School2 School3

X-Item    200       100           50       50      0

Schools can be added dynamically at any time. Now if I add the School4 with 40 units, I want to deduct the same from default school (DefaultSchool = 60, School4 = 40).

I can make this calculations in the converter and the ItemsSource also shows the updated value but it does not reflect on the UI.

What I use the TextBox's LostFocus event with MyDataGrid.Items.Refresh, it does update the UI, but every time on lost focus, the UI will also flickers, just like a refreshing web page).

I just need to update the current row. As I am using ExpandoObject, I can't use the INotifyPropertyChanged (I believe?), so what should be the best approach in this scenario?

So how should I update the UI?

Community
  • 1
  • 1
Learner
  • 1,490
  • 2
  • 22
  • 35

4 Answers4

1

I believe this isn't a problem with ExpandoObject not implementing INotifyPropertyChanged (because it does).

What I'm thinking is that your problem is the combination of INotifyCollectionChanged and using a converter. What happens is that converters are called when the property changes, but they aren't called when the collection changes. This will cause the UI not to update when an item is added or removed from the bound collection.

You can have a look at these questions for more information about this problem:

You could see if that's really your issue by setting a breakpoint in your converter and see if it's being called when you add the new item. If that's indeed the issue, you could either try to work your way around this without using a converter, or use a MultiValueConverter that will also receive the Count property (which will only act as a trigger), like so:

<DataGrid>
    <DataGrid.ItemsSource>
        <MultiBinding Converter="{local:MyConverter}">
            <Binding Path="Items" />
            <Binding Path="Items.Count" />
        </MultiBinding>
    </DataGrid.ItemsSource>
</DataGrid>
public class MyConverter : MarkupExtension, IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        // Your converter logic which will use values[0] (the bound collection).

        // Ignore anything else in the values[] array.
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}
Community
  • 1
  • 1
Adi Lester
  • 24,731
  • 12
  • 95
  • 110
1

Default DataGridColumn has one time binding, it means it loads and displays the value only first time, sine binding requires event wiring up, which is little performance overhead so they may have done like that. We had same problem, the only solution is to use cell template as shown below.

<DataTemplateGridColumn Header="DefaultSchool">
     <DataTemplateGridColumn.CellTemplate>
          <TextBlock Text="{Binding DefaultSchool}"/>
     </DataTemplateGridColumn.CellTemplate>
</DataGridTemplateColumn>

If you are generating column dynamically, then you will need something like this.

var t = new DataTemplate();
t.VisualTree = new FrameworkElementFactory((typeof(TextBlock));
t.VisualTree.SetBinding(new Binding(columnName));

var c = new DataGridTemplateColumn();
c.CellTemplate = t;
c.Header = columnName;

dg.Columns.Add( c );
Akash Kava
  • 39,066
  • 20
  • 121
  • 167
0

Make sure you have Mode=TwoWay in you XAML binding.

INotifyCollectionChanged will make sure that bindings will get notified when you add/remove items in a collection, but if you modify/update an object in the collection (object DefaultSchool) then INotifyCollectionChanged wont help you.

You need to implement INotifyPropertyChanged in the School class to make bindings get notified on updates/modifications on objects of that class within a collection.

Fredrik Claesson
  • 609
  • 7
  • 12
  • I am binding the ExpandoObject which i build dynamically, so i dont have any concrete school class. – Learner Oct 26 '12 at 12:21
0

Try Setting your window or usercontrol datacontext like this. datacontext = this.datacontext and the itemsource has the path to the data you want. If you dont set the datacontext then the itemsource has no way to bind to your objects. And after if it`s still not working, try making a datatemplate on you Items in the ItemSource. And last use an ObservableCollection so you dont have to implement those INotifyProperty...

Mihai
  • 518
  • 4
  • 12