C# 双向集合绑定同步/锁定
通过绑定同步两组数据的最佳方法是什么C# 双向集合绑定同步/锁定,c#,.net,wpf,binding,synchronization,C#,.net,Wpf,Binding,Synchronization,通过绑定同步两组数据的最佳方法是什么 Target = Custom Setters - raises custom events whenever something changed Source = ObservableCollection - raises events whenever collection changed 现在我的问题是,当我从一个集合(例如Source.CollectionChanged事件)收到更新时,我需要调用自定义targetsetter,并忽略从我的更新中调
Target = Custom Setters - raises custom events whenever something changed
Source = ObservableCollection - raises events whenever collection changed
现在我的问题是,当我从一个集合(例如Source.CollectionChanged事件)收到更新时,我需要调用自定义targetsetter,并忽略从我的更新中调用的事件
另一方面,当目标自定义事件被触发时,我需要更新源,但忽略CollectionChanged事件
目前,我正在保留对我的处理程序的引用,并在更新任何集合之前删除该引用。e、 g
private void ObservableCollection_OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
{
CustomObject.SelectionChanged -= CustomObject_SelectionChanged;
// Do change logic and update Custom Object....
CustomObject.SelectionChanged += CustomObject_SelectionChanged;
}
void CustomObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ObservableCollection.CollectionChanged -= ObservableCollection_OnCollectionChanged;
// Do change logic and update ObservableCollection...
ObservableCollection.CollectionChanged += ObservableCollection_OnCollectionChanged;
}
我已经看到,您可以使用if语句来检查更新是否来自源代码,以及它们是否来自源代码。e、 g
private void ObservableCollection_OnCollectionChanged2(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
{
if (BindingTargetUpdating) return;
BindingSourceUpdating = true;
// Do change logic and update Custom Object....
BindingSourceUpdating = false;
}
void CustomObject_SelectionChanged2(object sender, SelectionChangedEventArgs e)
{
if (BindingSourceUpdating) return;
BindingTargetUpdating = true;
// Do change logic and update ObservableCollection...
BindingTargetUpdating = false;
}
在Google+之后,搜索一无所获,我想看看其他人是如何做到这一点的,我在这里遗漏了什么可以解决这个问题的简单方法吗?(我知道这些示例不是线程安全的)
如果不是,首选的方式是什么?删除和附加处理程序,或设置布尔标志?什么性能更好(是的,我知道这不太可能造成瓶颈,但出于好奇)
我问这个问题的原因是,目前我正在实现附加的行为,对于每个行为,我正在创建两组字典,其中包含对每个对象处理程序的引用,因为状态必须传递
我似乎找不到.NET绑定类的绑定机制的源代码,看看MS是如何实现的。如果有人有这些链接,我们将不胜感激。最常用的方法是使用一种机制,即使用一个布尔值来跟踪更新发生的时间,并在其周围进行阻塞 就我个人而言,我更喜欢将该逻辑封装到一个实现
IDisposable
的小实用程序中。这样可以更容易地保证你总是自己打扫干净
可用于此目的的实用程序如下所示:
class Guard : IDisposable
{
readonly Func<bool> getter;
readonly Action<bool> setter;
readonly bool acquired = false;
public Guard(Func<bool> getter, Action<bool> setter)
{
this.getter = getter;
this.setter = setter;
if (this.getter() == false)
{
this.setter(true);
this.acquired = true;
}
}
public bool Acquired { get { return this.acquired; } }
void IDisposable.Dispose()
{
if (acquired)
{
this.setter(false);
}
}
}
这并不一定更短——它的编写时间可能更长,但可以保证在出现异常时释放块。如果您经常使用它,您总是可以子类化
Guard
,以减少使用量。对不起,我可能遗漏了一些内容,但是为什么您的设计要求您忽略每次发生变化时触发的一些事件?我真的搞不懂你想做什么。你能说说你想解决什么问题吗?因为如果你同时订阅双方,你会收到双方的通知。导致无限循环的。例如,Customibject引发它所更改的事件,调用my handler并更改绑定的集合,这反过来引发更改的事件,因此调用my collection changed handler编辑自定义对象。这再次引发了事件,你陷入了一个循环。我是说,设计你的程序时,你必须有意识地阻止它进入无限循环,这是一个相当大的代码味道。您不仅仅是通过INotifyPropertyChanged处理对集合的更改,还是我误解了您的目的?它们是由INotifyPropertyChanged处理的,我需要将DataGrid.SelectedCells、ScrollViewer.HorizontalOffset/ScrollViewer.VerticalOffset绑定到双向可观察的集合/对象。所有这些属性都是只读的,所以不,正常绑定将不起作用,它可能只起一种作用,但我需要将更新从我的ViewModel推送到我的ViewModel。我通常看到这是通过使用标志或某种范围设备来实现的。
private void ObservableCollection_OnCollectionChanged2(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
{
using(var guard = new Guard(() => BindingTargetUpdating, v => BindingTargetUpdating = value))
{
if (guard.Acquired)
{
// Do change logic and update Custom Object....
}
}
}