My version is supported for across thread. The following is the source code:
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Collections.ObjectModel; using System.Windows.Threading; namespace ObservableCollectionEx { public class ObservableCollectionEx<T> : ObservableCollection<T> { Dispatcher curerntDispatcher = (Application.Current as App).CurrentDispatcher; public new void Add(T item) { try { if (curerntDispatcher != null) { curerntDispatcher.BeginInvoke(() => { base.Add(item); }); } else { base.Add(item); } } catch (Exception exce) { // Utils.e(exce.Message, exce); } } public new bool Remove(T item) { try { if (curerntDispatcher != null) { curerntDispatcher.BeginInvoke(() => { base.Remove(item); }); } else { base.Remove(item); } } catch (Exception exce) { // Utils.e(exce.Message, exce); } return true; } public new void Clear() { try { if (curerntDispatcher != null) { curerntDispatcher.BeginInvoke(() => { base.Clear(); }); } else { base.Clear(); } } catch (Exception exce) { // Utils.e(exce.Message, exce); } } public void RemoveAt( int index) { try { if (curerntDispatcher != null) { curerntDispatcher.BeginInvoke(() => { base.RemoveAt(index); }); } else { base.RemoveAt(index); } } catch (Exception exce) { // Utils.e(exce.Message, exce); } } } }
关于具体的使用演示,XAML code:
< phone:PhoneApplicationPage x:Class ="ObservableCollectionEx.MainPage" xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone ="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell ="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d ="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc ="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable ="d" d:DesignWidth ="480" d:DesignHeight ="768" FontFamily =" {StaticResource PhoneFontFamilyNormal} " FontSize =" {StaticResource PhoneFontSizeNormal} " Foreground =" {StaticResource PhoneForegroundBrush} " SupportedOrientations ="Portrait" Orientation ="Portrait" shell:SystemTray.IsVisible ="True" > <!-- LayoutRoot is the root grid where all page content is placed --> < Grid x:Name ="LayoutRoot" Background ="Transparent" > < Grid.RowDefinitions > < RowDefinition Height ="Auto" /> < RowDefinition Height ="*" /> </ Grid.RowDefinitions > <!-- TitlePanel contains the name of the application and page title --> < StackPanel x:Name ="TitlePanel" Grid.Row ="0" Margin ="12,17,0,28" > < TextBlock x:Name ="ApplicationTitle" Text ="MY APPLICATION" Style =" {StaticResource PhoneTextNormalStyle} " /> < TextBlock x:Name ="PageTitle" Text ="page name" Margin ="9,-7,0,0" Style =" {StaticResource PhoneTextTitle1Style} " /> </ StackPanel > <!-- ContentPanel - place additional content here --> < Grid x:Name ="ContentPanel" Grid.Row ="1" Margin ="12,0,12,0" > < Button Content ="Button" Height ="72" HorizontalAlignment ="Left" Margin ="12,426,0,0" Name ="button1" VerticalAlignment ="Top" Width ="160" Click ="button1_Click" /> < ListBox Height ="283" HorizontalAlignment ="Left" Margin ="24,30,0,0" Name ="listBox1" VerticalAlignment ="Top" Width ="406" > < ListBox.ItemTemplate > < DataTemplate > < TextBox Name ="textBsdfd" Text =" {Binding Path=FullName} " ></ TextBox > </ DataTemplate > </ ListBox.ItemTemplate > </ ListBox > </ Grid > </ Grid > <!-- Sample code showing usage of ApplicationBar --> <!-- <phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="MenuItem 1"/> <shell:ApplicationBarMenuItem Text="MenuItem 2"/> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar> --> </ phone:PhoneApplicationPage >
下面是c# code:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Microsoft.Phone.Controls; using System.Threading; using System.Windows.Navigation; using System.Collections.ObjectModel; using System.Windows.Threading; namespace ObservableCollectionEx { public partial class MainPage : PhoneApplicationPage { private int temp = 0; ObservableCollectionEx2 < SourceCode > testConnection = null; public MainPage() { InitializeComponent(); (Application.Current as App).CurrentDispatcher = this.Dispatcher; testConnection = new ObservableCollectionEx2 < SourceCode >(); } protected override void OnNavigatedTo(NavigationEventArgs e) { (Application.Current as App).CurrentDispatcher = this.Dispatcher; this.listBox1.ItemsSource = testConnection; base.OnNavigatedTo(e); } private void button1_Click(object sender, RoutedEventArgs e) { Thread test1 = new Thread(DoWork); test1.Start(); Thread test2 = new Thread(DoWork2); test2.Start(); } private void DoWork(object etest) { try { int tempCount = 0; SourceCode code = new SourceCode(); code.FullName = temp.ToString(); temp++; lock (App.LockObject) { testConnection.Add(code); tempCount = testConnection.Count(); } Thread.Sleep(100); } catch (Exception exce) { int i = 0; } } private void DoWork2(object etest) { try { int tempCount = 0; SourceCode code = new SourceCode(); code.FullName = temp.ToString(); temp++; lock (App.LockObject) { testConnection.Add(code); tempCount = testConnection.Count(); } Thread.Sleep(100); } catch (Exception exce) { int i = 0; } } } }
下面是App的 C#文件:里面只需要加:
public static readonly object LockObject = new object(); // public static ObservableCollectionEx2<SourceCode> testConnection = new ObservableCollectionEx2<SourceCode>(); public Dispatcher CurrentDispatcher { get; set; }
大功告成,不需要你手动刷一下UI,所有的UI均自动刷新。