在MVVM之后的WPF应用程序中保存屏幕区域

时间:2016-12-22 11:06:08

标签: c# wpf image mvvm viewmodel

我有一个遵循MVVM架构的WPF应用程序。

在其中一个屏幕上是一个图表,需要在保存按钮单击时保存为图像文件。

我可以使用以下代码

中的代码保存图表
        Rectangle rect = new Rectangle(0, 0, 100, 100);
        Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
        Graphics g = Graphics.FromImage(bmp);
        g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);
        bmp.Save(fileName, ImageFormat.Jpeg);

但我需要能够在我的ViewModel中执行此操作。

为此,我通过了ActualHeight& ActualWidth作为按钮的Click命令的命令参数,方式如下:

<Button Content="Save" Command="{Binding MyViewModel.SaveCommand">
    <Button.CommandParameter>
        <MultiBinding Converter="{StaticResource DimensionConverter}">
             <Binding Path="ActualWidth" ElementName="MyChart"/>
             <Binding Path="ActualHeight" ElementName="MyChart"/>
        </MultiBinding>
    </Button.CommandParameter>
</Button>

在我的转换器中:

public class DimensionConverter : IMultiValueConverter
{
    public object Convert(object[] values, ...)
    {
        return values.Clone();
    }

    ...
}

然后,在命令执行逻辑中:

public void OnExecute(object parameter)
{
    var values = (object[])parameter;
    var width = (double)values[0];
    var height = (double)values[1];
    ...
}

但是,我还需要能够传递Chart控件和Origin的坐标。这可以使用PointToScreen方法完成。 但是如何将它们传递给视图模型,牢记MVVM?

还是有其他方法我可以捕捉屏幕区域和在MVVM架构中保存为图像?

1 个答案:

答案 0 :(得分:2)

  

还是有其他方法我可以捕捉屏幕区域和在MVVM架构中保存为图像?

该视图可以实现一个接口,该接口声明视图模型需要了解的所有信息的属性:

public interface IView
{
    double Width { get; }
    double Height { get; }
    double X { get; }
    double Y { get; }
}

然后,您可以将视图本身作为参数传递给视图模型的命令:

Command = new DelegateCommand<IView>(view => { /* do something */});

这不会破坏MVVM模式,因为视图模型没有直接对视图的引用。它只知道视图碰巧实现的接口。

接口甚至可以声明方法。在某些情况下,只有视图或视图中的控件可能知道如何序列化自身,然后您必须将此功能委托给视图,因为视图模型不能知道如何实际序列化控件。这是控件本身的实现细节。

视图模型仍然需要启动序列化过程,这意味着它必须能够以某种方式与视图进行通信。使用接口是实现此目的的一种方法。另一种方法是使用信使或事件聚合器。如果您想学习这个概念,请参阅以下博文:https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/