Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 双向集合绑定同步/锁定_C#_.net_Wpf_Binding_Synchronization - Fatal编程技术网

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....
       }
    }
}