2017-05-04 7 views
0

Ich versuche, eine einfache Aufgabe zu tun (ich denke schon). Ich möchte GUI dynamisch ändern, von der for-Schleife.
Lassen Sie sich meine XAML sehen:Binding Collection zu 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> 

Wie Sie sehen können, habe ich den Textblock, die Zahlen zeigt, Knopf, der das Programm und das Listenfeld beginnt, dass die Sammelgegenstände zeigen.

Nach Klick auf die Schaltfläche zeigt die erste Textblock (bindes MyValue) dynamische Werte, sondern auf das Listenfeld bekomme ich den nächsten Fehler:
„Diese Art von Collection Unterstützung seiner SourceCollection von einem Thread nicht ändert anders aus dem Dispatcher-Thread. "
Ich sah eine andere Antworten für den Fehler, kann aber nicht verstehen, wie es in meinem Fall zu implementieren.

Hier der C# -Code:

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; } 
    } 
} 

Vielen Dank!

+0

Wenn Ihr Programm auf 4,5 .NET läuft oder höher, dann gibt es keine Notwendigkeit, mit 'Dispatcher umgehen .Invoice'/'Dispatcher.BeginInvoke', wenn Sie Ihre Sammlung in einem anderen (Hintergrund-) Thread ändern möchten. Weisen Sie die WPF-Binding-Engine mithilfe von BindingOperations.EnableCollectionSynchronization an, dass andere Threads als der Dispatcher Ihre ObservableCollection ändern dürfen. Details in [diese Antwort auf eine verwandte Frage] (http://stackoverflow.com/a/31600890/2819245). – elgonzo

Antwort

1

ich die Button_Click Code ein wenig geändert haben, ist das Sie erreichen wollen, bitte vorschlagen:

private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     flag = !flag; 

     var list = new List <ChartPoint>(); 

     Task.Factory.StartNew(() => 
     { 
     for (int i = 0; i < 50000000; i++) 
     { 
      if (flag == false) break; 
      m.MyValue = i.ToString(); 
      Dispatcher.BeginInvoke(new Action(() => 
              { 
               m.MyCollection.Add(new ChartPoint 
                   { 
                    A = i, 
                    B = 2 * i 
                   }); 
              }), 
           DispatcherPriority.Background); 
     } 
     }); 
    } 
+0

Großartig !!! Kannst du bitte etwas erklären? Und wo kann ich darüber lesen? –

Verwandte Themen