Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.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# &引用;ItemsControl与其items源“不一致”;调用MessageBox.Show()时引发_C#_Wpf - Fatal编程技术网

C# &引用;ItemsControl与其items源“不一致”;调用MessageBox.Show()时引发

C# &引用;ItemsControl与其items源“不一致”;调用MessageBox.Show()时引发,c#,wpf,C#,Wpf,我对WPF非常陌生,我有以下问题: 我正试图开发一个实践应用程序来帮助我控制我的预算 我有一个这样的班级聚会: public class Partida { public delegate void PartidaChangedHandler(Partida p); public event PartidaChangedHandler OnPartidaChanged; private ObservableCollection<PartidaEntry> co

我对WPF非常陌生,我有以下问题:

我正试图开发一个实践应用程序来帮助我控制我的预算

我有一个这样的班级聚会:

public class Partida
{
    public delegate void PartidaChangedHandler(Partida p);
    public event PartidaChangedHandler OnPartidaChanged;
    private ObservableCollection<PartidaEntry> content;

    public Partida()
    {
        content = new ObservableCollection<PartidaEntry>();
        content.CollectionChanged += PartidaEntriesCollectionChanged;

    }

    public void PartidaEntriesCollectionChanged(object s, NotifyCollectionChangedEventArgs args)
    {
        if (OnPartidaChanged != null)
        {
            OnPartidaChanged(this);
        }
    }
}
当我在DataGrid中添加新行时,事件会正确触发,但是一旦执行MessageBox,我就会收到一条带有以下消息的
invalidoOperationException

ItemsControl与其items源不一致

你知道如何在不失去监听ObservaleCollection的CollectionChanged事件并在该事件发生后触发PartIdChanged的能力的情况下修复该问题吗

提前谢谢

另外,我想知道MessageBox和ItemControl到底有什么关系。。。如果MessageBox只显示一个简单的框,为什么会触发异常!:S

中的答案清楚地解释了发生的情况:在更改集合的操作正在进行时调用事件处理程序,调用
MessageBox.Show()
使dispatcher消息处理循环有机会再次开始处理消息。这会导致与WPF工作方式不兼容的重入:集合更改操作尚未完全解决,但UI有机会尝试运行在该操作完全解决之前不应运行的逻辑

换句话说,就像异常状态一样,控件处于不一致的状态,因为它被允许进行一些处理,而这些处理在完全处理集合更改之后才应该发生

我承认,另一个答案中的建议并不十分令人信服。就目前而言,这是一个合理的建议,但没有提供真正的替代方案

在您的场景中,在不改变任何其他实现的情况下,一个明显的解决方案是将消息框延迟到集合更改操作完全解决之后。您可以通过使用
Dispatcher.InvokeAsync()
方法来延迟对
MessageBox.Show()的调用执行:

当然,有一个问题是,显示消息框是否真的是处理事件的最佳方式。从您问题中有限的信息来看,我们并不清楚事件处理程序为何看起来如此。如果您确信在每次集合更改时显示消息框确实是正确的做法,那么上述操作应该可以解决您的问题


但您可能需要考虑将信息呈现给用户的其他方法,例如在UI中的状态字段中显示它,甚至提供一些事件日志,例如在多行文本框或列表框中。这类方法通常会涉及符合WPF中事件和数据处理正常流程的数据绑定,并且可以作为同步代码工作,而不会遇到您在这里看到的问题。

您可以发布ItemsControl的xaml吗?我在这里发现了另一个与此问题完全相同的问题()。选择的答案只是删除MessageBox.Show(),事实上他们说删除整个CollectionChanged事件处理程序。然而,这并不能真正解决问题@我的链接答案怎么解决不了你的问题?删除
MessageBox.Show()调用后是否仍会发生异常?你能澄清一下吗?
p.OnPartidaChanged += (Partida ppp) =>
{
    int foo = 5;
    MessageBox.Show("A partida has changed!");
};
p.OnPartidaChanged += (Partida ppp) =>
{
    int foo = 5;
    Dispatcher.InvokeAsync(() => MessageBox.Show("A partida has changed!"));
};