EntityFramework EntityState 和数据绑定以及 INotifyPropertyChanged

发布于 2024-08-28 13:16:37 字数 419 浏览 5 评论 0原文

我有一个显示 Shipment 实体的 WPF 视图。我有一个包含星号的文本块,它将提醒用户记录已更改但未保存。我最初希望将其可见性(使用转换器)绑定到 Shipment.EntityState 属性。

If value = EntityState.Modified Then
    Return Visibility.Visible
Else
    Return Visibility.Collapsed
End If

属性更新得很好,但视图不知道更改。我需要知道的是,如何让 UI 接收属性更改的通知。如果无法做到这一点,是否有一种好的方法可以编写我自己的 IsDirty 属性来处理编辑撤回(即,如果我更改属性的值,然后将其更改回原始值,则不会将其视为编辑,并声明保持不变)。

一如既往,任何帮助将不胜感激。

科里

I have a WPF view that displays a Shipment entity. I have a textblock that contains an asterisk which will alert a user that the record is changed but unsaved. I originally hoped to bind the visibility of this (with converter) to the Shipment.EntityState property.

If value = EntityState.Modified Then
    Return Visibility.Visible
Else
    Return Visibility.Collapsed
End If

The property gets updated just fine, but the view is ignorant of the change. What I need to know is, how can I get the UI to receive notification of the property change. If this cannot be done, is there a good way of writing my own IsDirty property that handles editing retractions (i.e. if I change the value of a property, then change it back to it's original it does not get counted as an edit, and state remains Unchanged).

Any help, as always, will be greatly appreciated.

Cory

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

乜一 2024-09-04 13:16:37

在与同样的问题苦苦挣扎一段时间后,这是一个对我有用的解决方案。
假设我有一个由 EF 生成的名为 Trip 的实体,我只需要通过部分类来扩展该类,如下所示。当您需要强制刷新 EntytyState 属性时(例如在调用上下文的 SaveChanges 方法之后),RaiseEntityStateChanged 方法非常有用。

partial class Trip
{
   bool _forced = false;
   System.Data.EntityState _lastState;

   public Trip()
   {
     _lastState = EntityState;
     this.PropertyChanged += (s, e) => 
     {
       if (_lastState != this.EntityState && e.PropertyName != "EntityState" || _forced)
       {
          _forced = false;
          OnPropertyChanged("EntityState");
       }

       _lastState = this.EntityState;
    };
  }

  public virtual void RaiseEntityStateChanged()
  {
     _forced = true;
     OnPropertyChanged("EntityState");
  }
}

After struggling with the same problem for a little bit, here is a solution that is working for me.
Lets say I have an entity called Trip that was generated by EF, I just needed to extend the class by means of partial class as showed below. The RaiseEntityStateChanged method is useful when you need to force a refresh of the EntytyState property, for example after calling the context's SaveChanges method.

partial class Trip
{
   bool _forced = false;
   System.Data.EntityState _lastState;

   public Trip()
   {
     _lastState = EntityState;
     this.PropertyChanged += (s, e) => 
     {
       if (_lastState != this.EntityState && e.PropertyName != "EntityState" || _forced)
       {
          _forced = false;
          OnPropertyChanged("EntityState");
       }

       _lastState = this.EntityState;
    };
  }

  public virtual void RaiseEntityStateChanged()
  {
     _forced = true;
     OnPropertyChanged("EntityState");
  }
}
无风消散 2024-09-04 13:16:37

我没有找到在现有属性上创建 XAML 绑定来执行您想要执行的操作的方法。但是您可以根据 EntityState 编写自己的 IsDirty 属性;您可以通过订阅基本 EntityObject 引发的 PropertyChanged 事件来更新此值。当然,您还需要为 IsDirty 引发 PropertyChanged 事件(以便通知 GUI)并在处理程序中忽略此事件(以防止无限递归)。
编辑:在OP提出的问题后添加了以下内容:

这就是我的看法,以便回答评论。

在shipment类中,可以添加:

public bool IsDirty { get { return EntityState == EntityState.Modified; } }

public Shipment() {
...
PropertyChanged += OnShipmentChanged;
}

private void OnShipmentChanged(object sender, PropertyChangedEventArgs pcea) {
    if (pcea.PropertyName != "IsDirty") { // prevent recursion
        OnPropertyChanged("IsDirty"); // notifies binding listener that the state has changed
    }
}

在晚上,我想到了另一种方法,即在每个Shipment属性上创建一个多重绑定(这将取代IsDirty属性的整个概念,并且实际上会回答原来的问题) 。如果只有几个 Shipment 属性,这可能是有意义的。我想说,如果超过 3 个,我们就应该忘记这个想法。

I don't see a way to create a XAML binding on an existing property to do what you are trying to do. But you could write your own IsDirty property, based on the EntityState; you could update this value by subscribing to the PropertyChanged event raised by the base EntityObject. Of course, you'll need to also raise a PropertyChanged event for IsDirty (so that the GUI is notified) and ignore this event in your handler (to prevent infinite recursion).
Edit: added the following after question by OP:

This is how I see it, in order to answer the comment.

In the shipment class, one can add:

public bool IsDirty { get { return EntityState == EntityState.Modified; } }

public Shipment() {
...
PropertyChanged += OnShipmentChanged;
}

private void OnShipmentChanged(object sender, PropertyChangedEventArgs pcea) {
    if (pcea.PropertyName != "IsDirty") { // prevent recursion
        OnPropertyChanged("IsDirty"); // notifies binding listener that the state has changed
    }
}

During the night, I thought of another way, which is to create a multi-binding on each Shipment property (which would replace this whole notion of an IsDirty property and would actually answer the original question). This could make sense if there are just a couple of Shipment properties. I'd say if there are more than 3, we should forget about this idea.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文