我有两个主题 - 让我们将它们命名为Calc线程和UI线程。在Calc线程内部,我刷新了一个ObservableCollection。我还有一个ObservableCollection的CollectionCHanged事件的处理程序。据我所知,处理程序在引发CollectionChanged事件的同一个线程中执行 - 所以这是在我的情况下刷新ObservableCollection的相同线程。因此,要刷新UI,我不能像在单线程应用程序中那样直接使用绑定 - 必须通过Dispatcher手动刷新UI。但是当我在UI中使用DataGrid时,我得到空行而不是任何数据,例如,当我使用ListBox时,会显示相应的数据:
数据网格情况向左,列表框情况向右
(列表框只是例如数据绑定和显示;我不希望数据显示在此列表框中,但是像数据网格一样(如果它按预期工作 - 不是在案例中)在图片上) - 列标题的表格)
好吧,我准备了代码,您可以复制并粘贴以重建问题:
C#
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Threading;
using System.Windows;
namespace WpfApplication1
{
public class MyClass
{
public int Integer { get; set; }
public string Str { get; set; }
}
public partial class MainWindow : Window
{
public ObservableCollection<MyClass> MyCollection { get; set; }
public MainWindow()
{
InitializeComponent();
MyCollection = new ObservableCollection<MyClass>();
MyCollection.CollectionChanged += MyCollection_CollectionChanged;
Thread t = new Thread(new ThreadStart(() =>
{
for (int i = 0; i < 10; i++)
{
MyCollection.Add(new MyClass()
{
Integer = i,
Str = "String" + i
});
Thread.Sleep(500);
}
}));
t.Start();
}
void MyCollection_CollectionChanged(
object sender,
NotifyCollectionChangedEventArgs e)
{
Dispatcher.Invoke(
() =>
{
foreach (var item in e.NewItems)
dataGrid.Items.Add((MyClass)item);
});
}
}
}
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">
<Grid>
<!--<ListBox Name="dataGrid">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Integer}" />
<TextBlock Text="{Binding Path=Str}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>-->
<DataGrid Name="dataGrid">
<DataGrid.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Integer}" />
<TextBlock Text="{Binding Path=Str}" />
</StackPanel>
</DataTemplate>
</DataGrid.ItemTemplate>
</DataGrid>
</Grid>
</Window>
答案 0 :(得分:1)
这是你想要的吗?
C#
namespace WpfApplication1
{
public class MyClass
{
public int Integer { get; set; }
public string Str { get; set; }
}
public partial class MainWindow : Window
{
public ObservableCollection<MyClass> MyCollection { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
MyCollection = new ObservableCollection<MyClass>();
Thread t = new Thread(new ThreadStart(() =>
{
for (int i = 0; i < 10; i++)
{
Dispatcher.Invoke(new Action(() =>
{
MyCollection.Add(new MyClass()
{
Integer = i,
Str = "String " + i
});
}));
}
}));
t.Start();
}
}
}
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">
<Grid>
<DataGrid Name="dataGrid" ItemsSource="{Binding MyCollection}">
<DataGrid.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Integer}" />
<TextBlock Text="{Binding Str}" />
</StackPanel>
</DataTemplate>
</DataGrid.ItemTemplate>
</DataGrid>
</Grid>
</Window>
其他方法是使用另一个List:
public partial class MainWindow : Window
{
private List<MyClass> _MyCollection;
public ObservableCollection<MyClass> MyCollection { get; set; }
private DispatcherTimer dispatcherTimer = new DispatcherTimer();
public MainWindow()
{
InitializeComponent();
DataContext = this;
MyCollection = new ObservableCollection<MyClass>();
_MyCollection = new List<MyClass>();
dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
Thread t = new Thread(new ThreadStart(() =>
{
for (int i = 0; i < 10; i++)
{
_MyCollection.Add(new MyClass()
{
Integer = i,
Str = "String " + i
});
Thread.Sleep(500);
}
}));
t.Start();
dispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
if (_MyCollection.Count != MyCollection.Count)
{
MyCollection.Add(_MyCollection[_MyCollection.Count - 1]);
}
}
}
第二次编辑你的例子:
namespace WpfApplication1
{
public class MyClass
{
public int Integer { get; set; }
public string Str { get; set; }
}
public partial class MainWindow : Window
{
private ObservableCollection<MyClass> _MyCollection;
public ObservableCollection<MyClass> MyCollection { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
MyCollection = new ObservableCollection<MyClass>();
_MyCollection = new ObservableCollection<MyClass>();
_MyCollection.CollectionChanged += new NotifyCollectionChangedEventHandler(_MyCollection_CollectionChanged);
Thread t = new Thread(new ThreadStart(() =>
{
for (int i = 0; i < 10; i++)
{
_MyCollection.Add(new MyClass()
{
Integer = i,
Str = "String " + i
});
Thread.Sleep(500);
}
}));
t.Start();
}
private void _MyCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Dispatcher.Invoke(new Action(
() =>
{
foreach (var item in e.NewItems)
MyCollection.Add((MyClass)item);
}));
}
}
}