C#: 转换为基类
C#: 转换为基类
我有一个包含链接的DataGrid列。单击链接时会打开一个文件。
我使用以下方法:
public void LinkClicked(object sender, RoutedEventArgs e) { var vm = (BasePartViewModel) DataContext; vm.OpenFile(); }
我想在基本ViewModel类中使用这段代码。
但是问题在于这个类型转换不起作用:
(BasePartViewModel) DataContext
因为实际上每个实现都是不同的。例如:
(BasePartViewModel) DataContext
而`Plug`是从`Part`派生出来的。如何使其正常工作,而不必在每个派生的ViewModel中实现这个方法?
在上面的代码中,出现了一个问题:从派生类(BasePartViewModel<Plug>)向基类(MyInterface<Part>)进行类型转换时出现了错误。
这个问题的原因是,C#在进行类型转换时,要求目标类型必须与实际类型相同或者是其基类。在这个例子中,BasePartViewModel<Plug>是从MyInterface<T>派生出来的,而MyInterface<Part>是从MyInterface<T>派生出来的,它们之间并没有直接的继承关系,因此无法进行类型转换。
解决这个问题的方法是,将MyInterface<T>声明为协变接口(covariant interface)。协变接口允许在派生接口中使用更具体的类型,而不仅仅是基类类型。通过将MyInterface<T>声明为协变接口,就可以在派生类(BasePartViewModel<Plug>)向基类(MyInterface<Part>)进行类型转换时,成功地进行类型转换。
具体实现的方法是,在MyInterface<T>接口的定义中,在T前面加上关键字“out”,即声明为协变接口。代码如下:
interface MyInterface<out T> { void OpenFile(); }
通过这样的修改,问题就得到了解决。现在,可以将BasePartViewModel<Plug>向MyInterface<Part>进行类型转换,并调用OpenFile方法,而不会出现错误。
问题:C#: Cast to Base
出现原因:在半 MVVM 实现中,需要进行向上转型(cast to base),但在完全 MVVM 实现中,不再需要 code behind,也不需要进行向上转型。
解决方法:采用 MVVM 的解决方案,使用命令模式(Command pattern)来处理事件处理程序。实现命令模式的最简单方法是创建一个可重用的命令类。如果已经使用某种 MVVM 框架,则通常会提供自己的实现。
具体步骤如下:
1. 理解命令模式的概念。
2. 确保视图绑定到的任何 ViewModel 都公开了所期望的命令属性,并且该属性是公有的并具有公有的 getter 方法。
通过以上步骤,可以摆脱在 xaml.cs 文件中编写代码和进行向上转型的需求。
以下是一个示例,展示如何将命令模式应用于带有超链接的 DataGrid 单元格:here。