このトピックに関する質問がたくさんありますが、C#とWPFの限られた経験では、答えは非常に複雑です。実行時に変更されるリストボックスにバインドされたコレクションを実装することをMicrosoftが(私にとって)これほど困難にしたとは信じられません。
取引は次のとおりです。アイテム(実際にはメールのリスト)を含むリストボックスがあります。何が起こるかというと、新しい電子メールが到着したとき、またはソースフォルダから削除されたときにリストボックスを更新する必要があります。簡単そうに聞こえますが、とにかく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()
{
}
}
}