将图像绘制到窗口中并进行更新

时间:2018-11-06 16:12:57

标签: c# wpf draw

我有一个不安全的类,该类会生成位图,该位图将转换为ToImageSource以便绘制到Window中。位图本身包含一个经常更新的正弦文本,我希望它从左向右“移动”(字幕样式?)。无论如何,它在WinForm中都可以正常工作,但是我对WPF窗口感到困惑。

以下是一些代码示例:

public AboutWindow()
{
    InheritanceBehavior = InheritanceBehavior.SkipAllNow;
    InitializeComponent();
    Initialize();
}

protected override void OnRender(DrawingContext drawingContext)
{
    base.OnRender(drawingContext);

    drawingContext.DrawImage(bitmapRender.WindowBitmap, drawingArea);

    if (!worker.IsBusy) 
        worker.RunWorkerAsync(); // BackgroundWorker in charge of updating the bitmap
}

void DispatcherTimerRender_Tick(object sender, EventArgs e) => InvalidateVisual();

我的问题是:窗口上没有任何显示,并且调用InvalidateVisual()的DispatchedTimer导致此异常:

  

System.InvalidOperationException:“不能使用与其父Freezable属于不同线程的DependencyObject。”

我看过其他线程,我知道WPF是一个保留的绘图系统,但无论如何我还是很乐意实现的。

关于实现这一目标的“最佳”方法的任何建议吗?

任何有用的解释/链接将不胜感激。

[编辑]

<Window x:Class="CustomerManagement.View.AboutWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
       mc:Ignorable="d" Height="450" WindowStartupLocation="CenterScreen" Width="800" ResizeMode="NoResize" AllowsTransparency="True" WindowStyle="None">
    <Grid KeyDown="Grid_KeyDown">
        <Image Width="800" Height="450" Source="{Binding 'Image'}" />
    </Grid>
</Window>

1 个答案:

答案 0 :(得分:1)

您应该使用在视图模型中将其Source属性绑定到ImageSource属性的Image元素。我认为,这是基于MVVM架构模式的“标准”方式,因此也是“最佳”方式。

<Image Source="{Binding Image}"/>

视图模型可能如下所示:

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private ImageSource image;
    public ImageSource Image
    {
        get { return image; }
        set
        {
            image = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Image)));
        }
    }
}

及其实例将分配给窗口的DataContext:

public AboutWindow()
{
    InitializeComponent();

    var vm = new ViewModel();
    DataContext = vm;
}

为了对其进行测试,下面的代码对目录中的图像文件进行幻灯播放。您也可以分配其他任何ImageSource-例如一个DrawingImage-到Image属性。

var imageFiles = Directory.GetFiles(..., "*.jpg");
var index = -1;
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };

timer.Tick += (s, e) =>
{
    if (++index < imageFiles.Length)
    {
        vm.Image = new BitmapImage(new Uri(imageFiles[index]));
    }
    else
    {
        timer.Stop();
    }
};

timer.Start();