Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 真正的MVVM和第三方控件_C#_Wpf_Mvvm_Infragistics_Xamdatagrid - Fatal编程技术网

C# 真正的MVVM和第三方控件

C# 真正的MVVM和第三方控件,c#,wpf,mvvm,infragistics,xamdatagrid,C#,Wpf,Mvvm,Infragistics,Xamdatagrid,在真正的MVVM模型中,我们不希望xaml.cs中有任何代码落后,也不希望viewModel具有视图引用。 但是,所有第三方控件都不能很好地支持真正的MVVM 在我的例子中,我使用Infragistics xamDatagrid控件,并希望将其数据导出到excel。将数据导出到数据网格excel的唯一方法是使用以下代码: xamDataGridExcelExporter.xamDataGridExcelExporter xamDataGridExcelExporter1 =

在真正的MVVM模型中,我们不希望xaml.cs中有任何代码落后,也不希望viewModel具有视图引用。 但是,所有第三方控件都不能很好地支持真正的MVVM

在我的例子中,我使用Infragistics xamDatagrid控件,并希望将其数据导出到excel。将数据导出到数据网格excel的唯一方法是使用以下代码:

xamDataGridExcelExporter.xamDataGridExcelExporter xamDataGridExcelExporter1 =       
   new xamDataGridExcelExporter.xamDataGridExcelExporter();   
xamDataGridExcelExporter1.Export(**this.xamDataGrid1**,   
   @"C:\Excel\ExportFile.xls");
但是,XamDataGridExcelExporter将输入作为this.xamDataGrid。xamDataGrid是视图而不是视图模型的一部分。
那么,我们如何处理这样的情况,我们需要viewModel中的视图实例。

我会使用代码隐藏,因为“问题”是由视图引起的,所以我会保留它


是的,这将破坏MVVM,但是使用这些控件它已经被破坏了。通过将解决方案保留在代码隐藏中,您将尽可能保持ViewModel的干净,因此当控件支持MVVM时,更容易清理。

MVVM禁止代码隐藏是一种常见的误解。事实上,代码隐藏是不可重用的,它与视图是不可分割的,因此如果没有自动化,它就无法进行单元测试。但它确实有它的用途

代码隐藏本身并没有什么不好的地方。事实上,它与支持视图的所有其他代码(如转换器、自定义控件等)差别不大。这些代码都不能通过视图模型单元测试进行测试。代码隐藏的唯一区别在于它的可重用性较差。但它仍然是您视图的一部分,视图也不错

通常,缺少代码隐藏是视图和视图模型之间清晰分离的良好指示器。然而,在一个干净的设计中,一些代码的存在通常仅仅表明标准控件、数据绑定和命令很难实现

在您的情况下,导出
XamDataGrid
肯定是视图特定的。它与您为视图选择的第三方库密切相关。因此,它不应该是视图模型的一部分,这是非常合理的


如果您仍然坚决反对任何代码隐藏,那么您可以使用行为,例如或编写功能,否则您会将这些功能放入代码隐藏中。只要意识到,即使是行为也仍然是视图的一部分,只是代码的可重用性更强。

您可以围绕xamDataGrid编写一个包装器,该包装器具有一个名为filename的dependencyproperty。然后,viewmodel可以绑定到此属性。当xamDataGrid检测到filename属性发生更改时,它可以执行您建议的代码。然后重置filename属性以获得进一步通知

此解决方案使代码不被代码隐藏,并使xamDataGrid负责导出其数据

-------编辑---------

第二个解决方案可以使用MVVM light messenger类。不要声明依赖属性,而是让包装器侦听消息。当viewmodel发送消息时(例如,可以将文件名作为参数),包装器就可以执行代码

乙二醇

您的问题有很多解决方案,您不必在视图中开始编写逻辑


我强烈建议在XAML中使用System.Windows.Interactivity.Interaction.Triggers,使用事件触发器调用XamDataGrid的事件,并使用“CallDataMethod”,它将调用您将在ViewModel上创建的自定义方法。其中最好的一点是,您将获得作为发送方的对象(XamDataGrid)引用

这将是纯粹的MVVM,您将能够实现您的目标。此外,我建议使用WPF DataGrid,它与XamDataGrid相比重量非常轻。仅当您使用此控件提供的一些主要功能时才使用XamDataGrid,因为仅初始化此UI元素处理器需要200毫秒或更长时间

<i:Interaction.Triggers>
                                <i:EventTrigger EventName="SelectedCellsChanged">
                                    <is:CallDataMethod Method="YourMethodNameInViewModel" />
                                </i:EventTrigger>
</i:Interaction.Triggers>

不要太担心它。是的,拥有“重”视图与MVVM(瘦视图、可测试性)的思想相反。但总有例外

这里的决定是使用“免费/现有”XAMDataGrid导出功能或编写自己的MVVM版本(位于ViewModel中)


如果选择选项1,除了设置View.DataContext=ViewModel并依赖数据绑定处理其余内容的常用方法外,还需要在ViewModel中缓存视图对象(使用ctor注入)

您可以将Excel导出器放置在触发导出的事件周围的位置,而不是将其保留在视图模型中

在您的行为中创建DataPresenter(xamdatagrid)类型依赖项属性,并将其绑定到XAMLcode中现有的xamdatagrid,以访问xamdatagrid。通过这种方式,您将在功能上实现,并且ViewModel将没有UI对象

<i:Interaction.Behaviors>
        <behav:ExcelExporterBehavior MyDataPresenter="{Binding ElementName=myxamdatagrid,Mode=OneTime}"></behav:ExcelExporterBehavior>
</i:Interaction.Behaviors>


如果MyDataPresenterExcelExporterBehavior行为中设置为任何其他UI控件(如任何要导出的按钮)的属性

我可以建议返回数据源而不是数据显示控件吗?意思是重新查询数据库或类似的东西?解决方案1和解决方案2在这里看起来都很合适。你能为解决方案2提供一个代码片段吗?我编辑了我的答案。我没有基础设施库,所以您的实现可能会有所不同,尽管总体方案应该是相同的。如果XamDatagrid被密封,那么您可以制作一个包装器。使用包装器的缺点是,您必须声明在xaml中使用的所有依赖属性,并将它们传递给用户。谢谢@Luc Bos。这是一个干净的解决方案,不仅在这种情况下有用,而且在第三方控制无效的情况下也有用
<i:Interaction.Triggers>
                                <i:EventTrigger EventName="SelectedCellsChanged">
                                    <is:CallDataMethod Method="YourMethodNameInViewModel" />
                                </i:EventTrigger>
</i:Interaction.Triggers>
public void YourMethodNameInViewModel(Object sender, EventArgs e)
    {}
<i:Interaction.Behaviors>
        <behav:ExcelExporterBehavior MyDataPresenter="{Binding ElementName=myxamdatagrid,Mode=OneTime}"></behav:ExcelExporterBehavior>
</i:Interaction.Behaviors>