CodeWarrior
CodeWarrior

Reputation: 7468

EntityFramework EntityState and databinding along with INotifyPropertyChanged

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

Upvotes: 2

Views: 1605

Answers (2)

MichelK7
MichelK7

Reputation: 21

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

Upvotes: 2

Timores
Timores

Reputation: 14589

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.

Upvotes: 1

Related Questions