0
我尝试做一些简单的任务(我想是这样)。我想从for循环动态地改变GUI。
让我们来看看我的XAML:绑定收藏到列表框
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel Name="MyPanel">
<TextBlock Text="{Binding MyValue}"></TextBlock>
<Button Click="Button_Click">OK</Button>
<ListBox Name="myList" ItemsSource="{Binding MyCollection}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding A}" Grid.Column="0"/>
<TextBlock Text="{Binding B}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Window>
正如你所看到的,我有一个显示号码的文本块,按钮时启动该程序,并在列表框中,应该显示藏品。
点击该按钮后,第一个文本块(bindes myvalue的)显示动态值,但在列表框中,我得到了一个错误:
“这种类型的CollectionView不会从不同的线程支持更改其SourceCollection从分派器线程。“
我看到了另一个错误的答案,但无法理解如何在我的情况下实现它。
这里的C#代码:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public static MyModel m;
public MainWindow()
{
m = new MyModel();
InitializeComponent();
MyPanel.DataContext = m;
}
bool flag = false;
private void Button_Click(object sender, RoutedEventArgs e)
{
flag = !flag;
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 5000000; i++)
{
if (flag == false) break;
m.MyValue = i.ToString();
m.MyCollection.Add(new ChartPoint { A = i, B = 2 * i });
}
});
}
}
public class MyModel : INotifyPropertyChanged
{
private string myValue;
public ObservableCollection<ChartPoint> MyCollection { get; set; }
public MyModel()
{
MyCollection = new ObservableCollection<ChartPoint>();
}
public string MyValue
{
get { return myValue; }
set
{
myValue = value;
RaisePropertyChanged("MyValue");
}
}
private void RaisePropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class ChartPoint
{
public int A { get; set; }
public int B { get; set; }
}
}
非常感谢!
如果你的程序在.NET 4.5或更高版本上运行,那么就没有必要处理'调度。调用'/'Dispatcher.BeginInvoke',只要你想在其他(后台)线程中改变你的集合。只需在'BindingOperations.EnableCollectionSynchronization'的帮助下指示WPF绑定引擎允许除Dispatcher之外的其他线程更改您的ObservableCollection。 [有关相关问题的这个答案]的详细信息(http://stackoverflow.com/a/31600890/2819245)。 – elgonzo