我有一个WPF应用程序正在数据库中查找新图像,如果出现问题,它会将图像添加到列表中。当引发该事件时,我希望它将图像添加到StackPanel中。
首先我尝试插入图像,但得到InvalidOperationException
说“调用线程必须是STA,因为许多UI组件都需要这个。”并提出:
public void Instance_GraphicChanged(object sender, PropertyChangedEventArgs e)
{
foreach (Model.Graphic item in Model.IncomingCall.Instance.Graphics)
{
if(!_strings.Contains(item.ImageId.ToString()))
{
Thread thread = new Thread( new ThreadStart(
delegate()
{
//sp_images StackPanel for Images
sp_images.Dispatcher.Invoke(
DispatcherPriority.Normal, new Action(
delegate()
{
Image img = new Image();
img.Source = item.ImageObj; //ImageObj returns a BitmapImage
sp_images.Children.Add(img);
}
));
}
));
_strings.Add(item.ImageId.ToString());
}
}
}
这不会引发任何异常,但实际上没有任何反应......
答案 0 :(得分:2)
参考我的评论,您可以尝试这样的事情:
<强> XAML 强>
<!-- ... Other XAML Code ... -->
<ItemsControl x:Name="sp_images">
<ItemsControl.ItemsPanel>
<StackPanel Orientation="Horizontal" />
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
代码背后
private readonly HashSet<string> mImageIds = new HashSet<string>();
private readonly ObservableCollection<BitmapImage> mImages = new ObservableCollection<BitmapImage>();
// ... Inside the constructor
{
InitializeComponent();
sp_images.ItemsSource = mImages;
}
public void Instance_GraphicChanged(object sender, PropertyChangedEventArgs e)
{
foreach (Model.Graphic item in Model.IncomingCall.Instance.Graphics)
{
// Have we already seen the image
if (mImageIds.Add(item.ImageId.ToString()))
{
// We've not seen the image yet, so add it to the collection
// Note: We must invoke this on the Dispatcher thread.
this.Dispatcher.BeginInvoke((Action)delegate()
{
mImages.Add(item.ImageObj);
});
}
}
}
这应该绕过您之前可能遇到的任何跨线程异常。它还应该允许您轻松地将新图像添加到ObservableCollection
,这将自动使用图像更新UI。此外,使用ItemTemplate
意味着您不必每次都实际构建UI; WPF将为您处理此事。
有关使用ObservableCollection
的详情,请参阅here。另外,请参阅此StackOverflow question以获取有关容器模板的说明。