【问题标题】:Databinding + DataGrid - how to connect?Databinding + DataGrid - 如何连接?
【发布时间】:2011-11-22 21:31:48
【问题描述】:

这个问题是我上一个问题DataGrid - grid selection is reset when new Data is arrived的结果

================================================ =======================

我有这样的DataGrid

<DataGrid AutoGenerateColumns="True" HorizontalAlignment="Stretch" Name="dataGrid1" VerticalAlignment="Stretch" ItemsSource="{Binding DataList}" IsReadOnly="True"/>

在我的 ViewModel 中有这样的字段:

public ObservableCollection<ConsoleData> DataList { get; set; }

还有这种每秒调用一次的方法:

private void model_DataArrived(List<ConsoleData> dataList)
{
    DataList.Clear();
    dataList.ForEach(x => DataList.Add(x));
}

================================================ =======================

我们发现,因为我调用了DataList.Clear,所以 UI 控件中的选择也会被清除,我不希望这种情况发生。很可能我不应该在ViewModel 中替换ConsoleData 的实例,而是应该update 这些实例。

但是ObservableCollection 观察添加/删除我猜并且不观察update 不是吗?那么如果我将update 实例DataBinding 将不起作用?

当前应用程序的另一个问题是dataList.ForEach(x =&gt; DataList.Add(x)); 强制数据绑定在每次迭代时执行,而不是仅在结束时执行?

总的来说,什么是做我想做的事情的正确方法,因为当前的应用程序不起作用并且有太多问题......

【问题讨论】:

    标签: c# wpf data-binding mvvm


    【解决方案1】:

    目前尚不清楚您打算如何更新ObservableCollection 中的项目。至少有两种方法可以做到这一点。一种方法是更新 ConsoleData 对象中更改的所有属性。在这种情况下,您将让 ConsoleData 实现 INotifyPropertyChanged。另一种方法是直接更新ObservableCollection 中的项目。为此,您可以使用ObservableCollectionSetItem 方法。这将引发CollectionChanged 事件,正如MSDN documentation for SetItem 所指示的那样。

    由于您已表明您正在使用 MVVM,因此普遍接受的做法是让您的 ObservableCollection 成为 ConsoleDataViewModel 的集合,而不是 ConsoleData。

    当前应用程序的另一个问题是dataList.ForEach(x =&gt; DataList.Add(x)); 强制数据绑定在每次迭代时执行,而不是仅在结束时执行?

    如果您修改您的 model_DataArrived 方法以更新而不是如上所述的清除/添加,我认为您不会遇到刷新问题。

    【讨论】:

    • hmm... 我想关注 MVVM 所以我可能应该使用ConsoleDataViewModel 而不是ConsoleData?我在哪里可以阅读更多相关信息? Jason Dolinger 扩展了 Dependency Object 并实现了一些 Dependency Properties 我应该这样做吗?看起来很复杂
    • 该视频是一种好方法,Josh Smith's MSDN article 是 MVVM 的另一个好资源。您可以使用 DependencyObject 或 INotifyPropertyChanged,您可能会注意到 Josh Smith 在文章中实现他的视图模型时根本没有使用 DependencyObject。这也是我碰巧在我自己的项目中使用的方法。不过,这两种方法都是有效的,如果您确实决定使用依赖属性,那么是的,您必须按照您在评论中描述的操作。
    【解决方案2】:

    问题是 ObservableCollection 在项目更改时没有通知;正如您所说,它仅在添加和删除项目时通知。为了解决这个问题,我创建了一个名为 VeryObservableCollection 的类。对于添加的每个对象,它将对象的 NotifyPropertyChanged 事件与触发 CollectionChanged 事件的处理程序挂钩。对于删除的每个对象,它都会删除处理程序。非常简单,应该可以解决您的问题。您只需要确保在集合中保存的对象上实现 NotifyPropertyChanged。例如:

    public class VeryObservableCollection<T> : ObservableCollection<T>
    
    /// <summary>
    /// Override for setting item
    /// </summary>
    /// <param name="index">Index</param>
    /// <param name="item">Item</param>
    protected override void SetItem(int index, T item)
    {
        try
        {
            INotifyPropertyChanged propOld = Items[index] as INotifyPropertyChanged;
            if (propOld != null)
                propOld.PropertyChanged -= new PropertyChangedEventHandler(Affecting_PropertyChanged);
        }
        catch (Exception ex)
        {
            Exception ex2 = ex.InnerException;
        }
        INotifyPropertyChanged propNew = item as INotifyPropertyChanged;
        if (propNew != null)
            propNew.PropertyChanged += new PropertyChangedEventHandler(Affecting_PropertyChanged);
    
        base.SetItem(index, item);
    }
    

    【讨论】:

      【解决方案3】:

      我认为你可以这样做

      private ObservableCollection<ConsoleData> dataList;
      public ObservableCollection<ConsoleData> DataList 
      { 
         get {return dataList; } 
         set {dataList = value;} 
      }
      

      您的数据操作仅访问字段dataList。一次完成操作强制 DataBinding 更新或重新分配它,以这种方式强制 Biding 向 WPF 发出通知。

      应该工作。

      【讨论】:

      • 但这应该可以解决UI持续刷新的问题,据我了解,这就是这个问题的问题。
      • 不,问题是如何做 1. 解决刷新 UI 问题。 2.解决“选择丢失”问题。 3.解决“性能”问题(如果存在)。 :)
      【解决方案4】:

      如果您的 ConsoleData 实现了 INotifyPropertyChanged,您可以简单地更新这些,您将在您的 ui 中看到更改 - 不会丢失选择。

      【讨论】:

        【解决方案5】:

        好的,首先我们需要了解作为任何Selector 控件(如ListBoxDataGrid 等)上的选择源的项目,如果删除,将失去选择。

        为此,请使用批量添加和单个通知FastObservableCollection

        但要保持这样的选择,一旦发生ClearAddRange,您必须将所选项目/值设置回DataGrid

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-06-06
          • 2019-06-06
          • 1970-01-01
          • 2016-04-13
          • 1970-01-01
          • 1970-01-01
          • 2018-08-04
          • 2012-09-25
          相关资源
          最近更新 更多