0

我看到很多关于这个主题的问题,而在我有限的 C# 和 WPF 经验中,答案过于复杂。我不敢相信微软让(对我来说)实现绑定到在运行时更改的列表框的集合变得如此困难。

这是交易:我有一个包含项目的列表框(实际上是电子邮件列表)。发生的情况是,当新电子邮件到达或从源文件夹中删除时,我需要刷新列表框。听起来很容易,但无论如何操作 Observable Collection 都会导致可怕的“这种类型的 CollectionView 不支持从与 Dispatcher 线程不同的线程对其 SourceCollection 的更改。”

所以暂时不要介意通过编写调度程序来规避这个问题。是否有一些“正常”的方式来操作不是来自另一个线程的集合?——这就是我困惑的地方。我还能在哪里修改集合?如果这是预期的,我很乐意将我的代码放在那里。

我当前的实现——很可能很糟糕——是将Folder.Items 事件处理程序放在集合类本身中,然后从集合(即它本身)中添加/删除电子邮件。这不起作用,我真的不明白如何做到这一点。


好的,我整理了这个代码示例。这不是我的应用程序,但它几乎代表了我(错误地)处理事情的方式......这将引发“无法更新源收集线程错误”。该示例分为 3 个部分,首先是 XAML 标记,然后是 Main 类和方法以及 ObservableCollection 类。

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
    x:Class="WpfApplication1.MainWindow"
    x:Name="Window"
    Title="MainWindow"
    Width="640" Height="480">

    <Grid x:Name="LayoutRoot" >
        <Border BorderBrush="#FF404020" BorderThickness="5" Margin="0" Background="#FFFFFFC0" CornerRadius="25">
            <ListBox x:Name="lbList" Margin="50" FontSize="21.333" DisplayMemberPath="Subject"/>
        </Border>
    </Grid>
</Window>

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Outlook;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MailList ml = new MailList();

        public MainWindow()
        {
            this.InitializeComponent();

            Microsoft.Office.Interop.Outlook.Application olApp = Marshal.GetActiveObject("Outlook.Application") as Microsoft.Office.Interop.Outlook.Application;

            Folder f = (Folder)olApp.Session.PickFolder();  // User picks MAPI Folder
            f.Items.ItemAdd += new ItemsEvents_ItemAddEventHandler(this.UpdateListBox);     //Folder.Item add event, calls  UpdateListBox
            foreach (object o in f.Items)
            {
                if (o is MailItem)
                {
                    ml.Add((MailItem)o);    //Add Mailitems to ml collection
                }
            }

            Binding b = new Binding();      //create binding for ListBox
            b.Mode = BindingMode.OneWay;
            lbList.DataContext = ml;
            lbList.SetBinding(ListBox.ItemsSourceProperty, b);
        }

        public void UpdateListBox(object o)     //Add new MailItem to ml collection
        {
            if (o is MailItem)
            {
                ml.Add((MailItem)o);
            }
        }

    }
}

using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using Microsoft.Office.Interop.Outlook;

namespace WpfApplication1
{
    public class MailList : ObservableCollection<MailItem>
    {
        public MailList()
            : base()
        {
        }
    }
}
4

1 回答 1

1

将集合更改分派到 UI 线程应该是什么问题?据我所知,这是通常的方式。

于 2012-08-21T22:31:34.110 回答