【问题标题】:DataContext Refresh and PropertyChanging & PropertyChanged EventsDataContext Refresh 和 PropertyChanging & PropertyChanged 事件
【发布时间】:2010-10-11 10:28:11
【问题描述】:

我的情况是,我从外部来源获悉某个特定实体已在我当前的数据上下文之外被更改。我能够找到实体并像这样调用刷新

MyDataContext.Refresh(RefreshMode.OverwriteCurrentValues, myEntity);

并且实体上已更改的属性已正确更新。但是,当刷新发生时,INotifyPropertyChanging INotifyPropertyChanged 似乎都没有出现,这使我的 UI 显示不正确的信息。

我知道 Refresh() 未能在实体上使用正确的属性 getter 和 setter 来引发更改通知事件,但也许还有另一种方法可以完成同样的事情?

我做错了吗? 有没有比刷新更好的方法? 如果刷新是唯一的选择,有没有人可以解决?

【问题讨论】:

    标签: linq linq-to-sql datacontext inotifypropertychanged


    【解决方案1】:

    我遇到了类似的问题。我绑定到 TreeView 并且需要调用 Refresh 以响应用户取消编辑操作。 Refresh() 方法乖乖的把原来的值全部放回去了,但是这在我的 TreeView UI 中并没有体现出来。在咨询了全能的谷歌之后,我发现了这个解决方案:

    CollectionViewSource.GetDefaultView(treeViewClusters.ItemsSource).Refresh();
    

    这似乎迫使我的 TreeView 更新所有内容。唯一的缺点(这是一个非常大的缺点)是它似乎折叠了所有的树节点,这导致用户失去了他们的位置。我也可以将我的ItemsSource 设置为 null 并再次返回...同样的效果,尽管如果你有一堆绑定的文本框或其他东西,这种方法会更简单,因为你不需要重新绑定每一个.

    还有比这更好的解决方案吗?

    已编辑: 是的,有...

    我的一个比我聪明的同事想出了这个解决方案,这似乎可以解决问题。在 Linq2Sql 对象的部分类中,添加以下代码:

    public void SendPropertiesChanged()
    {
         foreach (System.Reflection.PropertyInfo prop in this.GetType().GetProperties())
         SendPropertyChanged(prop.Name);
    }
    

    你可以在你的应用程序代码中调用它:

    context.Refresh(RefreshMode.OverwriteCurrentValues, employee);
    employee.SendPropertiesChanged();
    

    所有 UI 元素都会收到消息,并相应地更新自己。这甚至适用于树视图控件以及您不希望 UI 在刷新绑定时出现“重置”的情况。

    【讨论】:

      【解决方案2】:

      如果您知道调用 Refresh(),为什么不直接在此时刷新 UI?

      PropertyChanging 和 PropertyChanged 是通过在 LINQtoSQL DBML 生成的实体类上调用 setter 来调用的。调用 Refresh() 不会这样做:

      [Column(Storage="_DisplayName", DbType="VarChar(50) NOT NULL", CanBeNull=false)]
      public string DisplayName
      {
          get
          {
              return this._DisplayName;
          }
          set
          {
              if ((this._DisplayName != value))
              {
                  this.OnDisplayNameChanging(value);
                  this.SendPropertyChanging();
                  this._DisplayName = value;
                  this.SendPropertyChanged("DisplayName");
                  this.OnDisplayNameChanged();
              }
          }
      }
      

      【讨论】:

      • Rex,Refresh() 是在控制器/“几乎业务层”级别完成的,它离 UI 很远,因此手动刷新是不可能的。如果 Refresh() 改变了实体数据,它应该引发改变的事件——它没有这样做的事实对我来说似乎是一个严重的疏忽。
      • @Scott 也许这是一个疏忽,但这是我们无法更改的代码,而您的却是。为什么不在调用 Refresh() 时向 DataContext 类添加一个事件并从 UI 附加到该类?这与您从实体中的事件获得的 SoC 很接近。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-09
      • 1970-01-01
      • 2010-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多