UI不会更新ExpandoObject列表

时间:2012-10-18 12:09:39

标签: c# wpf user-interface inotifypropertychanged expandoobject

我已按照this链接实现了动态dataGrid。

我使用Converter绑定来自ExpandoObject的值。列显示了学校总单位等值。

Item      ItemCount DefaultSchool School1  School2 School3

X-Item    200       100           50       50      0

学校可以随时动态添加。现在,如果我将School4添加到40个单位,我想从默认学校中扣除相同的数量(DefaultSchool = 60,School4 = 40)。

我可以在转换器中进行此计算,而ItemsSource也会显示更新的值,但它不反映在UI上。

我将TextBox的LostFocus事件与MyDataGrid.Items.Refresh一起使用,它确实更新了用户界面,但每次失去焦点时,用户界面也会闪烁,就像刷新网页一样。)

我只需要更新当前行。当我使用ExpandoObject时,我无法使用INotifyPropertyChanged(我相信?),那么在这种情况下最佳方法应该是什么?

那么我应该如何更新UI?

4 个答案:

答案 0 :(得分:1)

我认为ExpandoObject没有实施INotifyPropertyChanged(因为it does),这不是问题。

我在想的是你的问题是INotifyCollectionChanged和使用转换器的组合。发生的变化是在属性更改时调用转换器,但在集合更改时不会调用它们。这将导致UI在绑定集合中添加或删除项目时不会更新。

您可以查看这些问题,了解有关此问题的更多信息:

您可以通过在转换器中设置断点并查看是否在添加新项目时调用它来查看这是否真的是您的问题。如果这确实是问题,你可以尝试不使用转换器来解决这个问题,或者使用也会收到MultiValueConverter属性的Count(它只会作为触发器),像这样:

<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;
    }
}

答案 1 :(得分:1)

默认DataGridColumn有一个时间绑定,这意味着它只加载并显示第一次的值,正弦绑定需要事件连接,这是很小的性能开销,所以他们可能已经这样做了。我们有同样的问题,唯一的解决方案是使用如下所示的单元格模板。

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

如果要动态生成列,那么您将需要这样的内容。

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 );

答案 2 :(得分:0)

确保XAML绑定中有Mode = TwoWay。

INotifyCollectionChanged将确保在添加/删除集合中的项目时通知绑定,但如果您修改/更新集合中的对象(对象DefaultSchool),则INotifyCollectionChanged将无法帮助您。

您需要在School类中实现INotifyPropertyChanged,以便在集合中对该类的对象进行更新/修改时通知绑定。

答案 3 :(得分:0)

尝试像这样设置窗口或usercontrol datacontext。 datacontext = this.datacontext 并且itemsource具有所需数据的路径。 如果您没有设置datacontext,那么itemsource无法绑定到您的对象。 如果它仍然不起作用,请尝试在ItemSource中为您的项目创建数据窗口。 最后使用ObservableCollection,所以你不必实现那些INotifyProperty ......