私は簡単な作業をしようとします(私はそう思います)。 forループからGUIを動的に変更したい。
はのは、私のXAMLを見てみましょう:ListBoxへのコレクションのバインド
<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への変更をサポートしていません。 Dispatcherスレッドから取得します。
私はこのエラーの別の回答を見ましたが、私の場合はそれを実装する方法を理解できません。
ここで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以降で実行されている場合は、ディスパッチャ 'に対処する必要はありません.Invoke'/'Dispatcher.BeginInvoke'を呼び出すと、他の(バックグラウンド)スレッドでコレクションを変更したいときに便利です。 'BindingOperations.EnableCollectionSynchronization'の助けを借りて、Dispatcher以外のスレッドがObservableCollectionを変更することを許可されているWPFバインディングエンジンに指示してください。 [関連する質問に対するこの回答]の詳細(http://stackoverflow.com/a/31600890/2819245)。 – elgonzo