在WPF中将图像添加到StackPanel

时间:2011-12-14 10:51:54

标签: c# wpf

我有一个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());
        }
    }
}

这不会引发任何异常,但实际上没有任何反应......

1 个答案:

答案 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以获取有关容器模板的说明。