按照 MVVM 在 WPF 应用程序中保存屏幕区域
Save a region of screen in WPF app following MVVM
我有一个遵循 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];
...
}
但是,我还需要能够通过 Origin 传递图表控件的坐标。这可以使用 PointToScreen 方法来完成。 但是我怎样才能将它们传递给 MVVM 的视图模型呢?
或者是否有任何其他方法可以捕获屏幕区域并在 MVVM 架构中另存为图像?
Or is there any other way that I can capture a region of a screen & save as image in MVVM architecture?
视图可以实现一个接口,为视图模型需要了解的所有信息声明属性:
public interface IView
{
double Width { get; }
double Height { get; }
double X { get; }
double Y { get; }
}
然后您可以将视图本身作为参数传递给视图模型的命令:
Command = new DelegateCommand<IView>(view => { /* do something */});
这不会破坏 MVVM 模式,因为视图模型没有 直接 对视图的引用。它只知道视图碰巧实现的接口。
接口甚至可以声明方法。在某些情况下,只有视图或视图中的控件可能知道如何序列化自身,然后您必须将此功能委托给视图,因为视图模型不应该知道如何实际序列化控件。这是控件本身的一个实现细节。
视图模型仍然必须启动序列化过程,这意味着它必须能够以某种方式与视图进行通信。使用接口是一种方法。另一种方法是使用信使或事件聚合器。想了解概念的请参考以下博客post:https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/.
我有一个遵循 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];
...
}
但是,我还需要能够通过 Origin 传递图表控件的坐标。这可以使用 PointToScreen 方法来完成。 但是我怎样才能将它们传递给 MVVM 的视图模型呢?
或者是否有任何其他方法可以捕获屏幕区域并在 MVVM 架构中另存为图像?
Or is there any other way that I can capture a region of a screen & save as image in MVVM architecture?
视图可以实现一个接口,为视图模型需要了解的所有信息声明属性:
public interface IView
{
double Width { get; }
double Height { get; }
double X { get; }
double Y { get; }
}
然后您可以将视图本身作为参数传递给视图模型的命令:
Command = new DelegateCommand<IView>(view => { /* do something */});
这不会破坏 MVVM 模式,因为视图模型没有 直接 对视图的引用。它只知道视图碰巧实现的接口。
接口甚至可以声明方法。在某些情况下,只有视图或视图中的控件可能知道如何序列化自身,然后您必须将此功能委托给视图,因为视图模型不应该知道如何实际序列化控件。这是控件本身的一个实现细节。
视图模型仍然必须启动序列化过程,这意味着它必须能够以某种方式与视图进行通信。使用接口是一种方法。另一种方法是使用信使或事件聚合器。想了解概念的请参考以下博客post:https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/.