DataContext Refresh and PropertyChanging & Propert

2019-07-26 22:14发布

I'm in a situation where I am being informed from an outside source that a particular entity has been altered outside my current datacontext. I'm able to find the entity and call refresh like so

MyDataContext.Refresh(RefreshMode.OverwriteCurrentValues, myEntity);

and the properties which have been altered on the entity are updated correctly. However neither of the INotifyPropertyChanging INotifyPropertyChanged appear to be raised when the refresh occurs and this leaves my UI displaying incorrect information.

I'm aware that Refresh() fails to use the correct property getters and setters on the entity to raise the change notification events, but perhaps there is another way to accomplish the same thing?

Am I doing something wrong? Is there a better method than Refresh? If Refresh is the only option, does anyone have a work around?

2条回答
爷、活的狠高调
2楼-- · 2019-07-26 22:33

I had a similar issue. I was binding to a TreeView and needed to call Refresh in response to the user canceling an edit operation. The Refresh() method obediently puts all the original values back, but this was not reflected in my TreeView UI. After consulting with the almighty Google, I came across this solution:

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

This seems to force my TreeView to update everything. The only drawback (and it's a pretty major one) is that it seems to collapse all the tree nodes, which causes the user to lose their place. I could just as well set my ItemsSource to null and back again...same effect, although this method would be simpler if you had a bunch of bound text boxes or something, since you wouldn't need to rebind every single one.

Is there a better solution than this?

EDITED: Yes there is...

A smarter-than-me coworker of mine came up with this solution, which seems to do the trick. In your partial class for the Linq2Sql object, add the following code:

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

The you can just call this in your application code:

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

All UI elements get the message, and update themselves appropriately. This even works for treeview controls and things like that where you don't want the UI to appear to "reset" when you refresh the bindings.

查看更多
走好不送
3楼-- · 2019-07-26 22:42

If you know to call Refresh(), why not just go ahead and refresh the UI at that point anyway?

PropertyChanging and PropertyChanged are invoked by invoking the setter on a LINQtoSQL DBML-generated entity class. Calling Refresh() does not do that:

[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();
        }
    }
}
查看更多
登录 后发表回答