Wpf 当我打印控件时,它不会显示视图模型中的数据

Wpf 当我打印控件时,它不会显示视图模型中的数据,wpf,mvvm,printing,Wpf,Mvvm,Printing,我正在尝试使用以下代码打印用户控件: myUserControlView myView = new myUserControlView(); myUserControlViewModel myViewModel = new myUserControlViewModel(paramItemWithData); myView.DataContext = myViewModel; int myFactor; myFactor = 6; myView.Measure(new Size(794 *

我正在尝试使用以下代码打印用户控件:

myUserControlView myView = new myUserControlView();
myUserControlViewModel myViewModel = new myUserControlViewModel(paramItemWithData);
myView.DataContext = myViewModel;



int myFactor;
myFactor = 6;

myView.Measure(new Size(794 * 1, 1122 * 1));
myView.Arrange(new Rect(new Size(794 * 1, 1122 * 1)));
myView.UpdateLayout();

System.Windows.Media.Imaging.RenderTargetBitmap rtb = new System.Windows.Media.Imaging
    .RenderTargetBitmap(794 * myFactor, 1122 * myFactor, 96 * myFactor, 96 * myFactor, System.Windows.Media.PixelFormats.Pbgra32);
    rtb.Render(myView);



System.Windows.Media.Imaging.PngBitmapEncoder encoder = new System.Windows.Media.Imaging.PngBitmapEncoder();
System.IO.MemoryStream ms = new System.IO.MemoryStream();
encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(rtb));
encoder.Save(ms);
System.Drawing.Image img = System.Drawing.Image.FromStream(ms);
e.Graphics.DrawImage(img, new System.Drawing.PointF());
视图只有一个datagrid,其中ItemsSource是视图模型中的一个属性。打印时,结果是可以看到datagrid的标题,但它没有行

我想这是关于刷新视图以从视图模型中获取数据,因为视图模型正确地从数据库中获取数据,但它不会显示在打印文档中

谢谢

编辑:

我注意到问题是当我从数据库中获取数据时,方法是异步的。如果不是asyc,它工作正常

因此,我将分享我的mie模型代码:

public MyViewModel()
{
    Task.Run(() => getDataAsync().ConfigureAwait(false));
}


private ObservableCollection<MyType> _myItems = new ObservableCollection<MyType>();
public ObservableCollection<MyType> MyItems
{
    get { return _myItems; }
    set
    {
        _myItems = value;
        base.RaisePropertyChangedEvent("MyItems");
    }
}


private async Task getDataAsync()
{
    using(ContextEfCore myDbContext = new ContextEfCore(_optionsDbContext))
    {
        MyItems = new ObservableCollection<MyType>(await myDbCOntext.MyType.ToListAsync());
    }
}


private void getData()
{
    using(ContextEfCore myDbContext = new ContextEfCore(_optionsDbContext))
    {
        MyItems = new ObservableCollection<MyType>(await myDbCOntext.MyType.ToList());
    }
}
如果我使用异步方法,它不会显示行,但是如果我使用非异步方法,它会按预期工作

那么,如何使用异步方法按预期工作呢?我希望避免使用该方法的两个版本,我只希望使用异步方法


谢谢。

有两件事打破了MVVM结构,我认为您正在使用MVVM结构

尽量不要在构造函数的类外调用。如您所见,您不能等待构造函数。这是通过设计实现的,因为在某种意义上,构造函数可以位于不同的线程上。因此,在您的示例中,如果调用以获取数据,线程的上下文可能与回调不同。如果发生这种情况,您的数据或方法可能会导致错误

您正在使用Task.Run或Task.Start(而不是I/O线程)为后台线程使用任务结构。由于获取数据是I/O绑定的任务,而getDataAsync是IO绑定的,所以您可以等待该方法

异步执行此操作的一个好方法是公开在创建视图后激发的方法。MVVM允许视图了解视图模型

我的建议是公开getDataAsync方法,或者创建一个新方法,比如PrepareViewModel,并在视图中调用它,或者如果有,在导航总线中调用它

下面是如何将其编码为事件处理程序

视图模型:

public class MyViewModel
{
    public async Task PrepareViewModelAsync()
    {
        await getDataAsync();
        // add other code to prepare the view model.
        // ...
    }

    private async Task getDataAsync()
    {
        using(ContextEfCore myDbContext = new ContextEfCore(_optionsDbContext))
        {
            MyItems = new ObservableCollection<MyType>(await myDbCOntext.MyType.ToListAsync());
        }
    }
}
Task.Run=>getDataAsync.ConfigureWaitFalse您对任务的工作方式没有很好的理解。你应该找一本关于这个主题的书读一读。
<Window x:Class="WpfApp1.MainWindow"
        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"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded">
    <Grid>
    </Grid>
</Window>
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
    // get the view model from the data context
    var viewModel = DataContext as MyViewModel;

    if (viewModel != null) await viewModel.PrepareViewModelAsync();
}