C# MVVM中XAML到PNG的转换

C# MVVM中XAML到PNG的转换,c#,wpf,xaml,C#,Wpf,Xaml,如何将XAML转换(如整个网格或viewbox)为png文件 我需要从ViewModel级别执行此操作 我无法在ViewModel中调用,因为我无权访问该对象 有一种简单而愉快的方法吗?视图将负责根据您链接到的答案导出您在屏幕上看到的元素 视图模型应该初始化操作。它可以通过多种不同的方式实现这一目标 一个选项是使用事件聚合器或messenger向视图发送松散耦合的事件或消息。有关此主题的更多信息,请参阅以下博文: 另一个选项是向视图模型中注入对视图的松散引用。视图实现一个接口,并使用构造函数注入

如何将XAML转换(如整个网格或viewbox)为png文件

我需要从ViewModel级别执行此操作

我无法在ViewModel中调用,因为我无权访问该对象


有一种简单而愉快的方法吗?

视图将负责根据您链接到的答案导出您在屏幕上看到的元素

视图模型应该初始化操作。它可以通过多种不同的方式实现这一目标

一个选项是使用事件聚合器或messenger向视图发送松散耦合的事件或消息。有关此主题的更多信息,请参阅以下博文:

另一个选项是向视图模型中注入对视图的松散引用。视图实现一个接口,并使用构造函数注入或属性注入将自身注入视图模型,例如:

public interface IExport
{
    void Export(string filename);
}

public partial class MainWindow : Window, IExport
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModel(this);
    }

    public void Export(string filename)
    {
        //export...
    }
}

public class ViewModel
{
    private readonly IExport _export;

    public ViewModel(IExport export)
    {
        _export = export;
    }

    public void DoExport()
    {
        //...
        _export.Export("pic.png");
    }
}
这样,视图模型只知道一个接口,并且对接口有深度。它不依赖于视图,在单元测试中,您可以轻松地提供
IExport
接口的模拟实现

但是,视图模型将永远也不应该有任何访问要导出的实际图元的权限。这些属于视图。

您需要类似的东西-VM从视图中获取某些东西的一种方式。如果不想为此安装全新的框架,只需使用Func属性:

ViewModel.GetBitmapOfElement = elementName =>
{
   var uiElement = FindElementByName(elementName); // this part you have figure out or just always use the same element

  return ExportToPng(FrameworkElement element); // this is the function form the link form your answer modified to return the bitmap instead of saving it to file
}
您的虚拟机:

public Func<string, Bitmap> GetBitmapOfElement {get;set;}
...

//in some command
 var bmp = GetBitmapOfElement("elementName");

如果需要异步,只需将属性类型更改为
Func
,并在视图中分配异步函数

那么依赖属性呢?考虑以下用于传递数据的类(数据可以是流或任何您想要的):

然后创建一个usercontrol并注册一个请求者类型的依赖属性

public partial class MyUserControl : UserControl
{
    public static readonly DependencyProperty RequesterProperty
        = DependencyProperty.Register("Requester", typeof(Requester), typeof(MainWindow),
            new PropertyMetadata(default(Requester), OnRequesterChanged));

    public MyUserControl()
    {
        InitializeComponent();
    }

    public Requester Requester
    {
        get => (Requester) GetValue(RequesterProperty);
        set => SetValue(RequesterProperty, value);
    }

    private static void OnRequesterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        => ((Requester) e.NewValue).DataRequested += ((MyUserControl) d).OnDataRequested;

    private void OnDataRequested()
    {
        Requester.Data = "XD";
    }
}
您的视图模型如下所示:

public class MainWindowViewModel
{
    public Requester Requester { get; } = new Requester();

    public void RequestData() => Requester.RequestData();
}
在XAML中,只需将控件中的依赖项属性绑定到视图模型中的属性:

<Window x:Class="Test.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:Test"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>
    <Grid>
        <local:MyUserControl Requester="{Binding Requester}"/>
    </Grid>
</Window>


为什么必须在viewmodel中操作视图对象?我将在视图中进行转换,然后通过绑定依赖属性将结果传递给viewmodel。如果需要从viewmodel执行此过程,则可以使用另一个绑定dp来启动此过程。@Andy您能谈谈如何将其直接转换为xaml吗?也许是一个例子?你把代码翻译成一个文件。谷歌多一点,你可以找到类似的翻译文件流,所以它都在内存中。如果代码只在一个地方或可重用类中使用,请将其放在代码后面。您甚至可以将其放在控件中(没有ui),并向其添加依赖项属性,以便可以将要转换的控件绑定到一个属性,并将结果绑定到viewmodel中的属性。然后可能会绑定另一个依赖项属性,以便您可以从viewmodel启动该过程。如果这仍然没有意义,请回来,我稍后会编写一些内容。再仔细考虑一下,最好只使用依赖项对象,而不是控件。您需要某种形式的do,以便具有依赖项属性和绑定。这不适合一个附加的依赖属性或行为。国际海事组织。
<Window x:Class="Test.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:Test"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>
    <Grid>
        <local:MyUserControl Requester="{Binding Requester}"/>
    </Grid>
</Window>