C#无法从类类型转换为接口类型

时间:2016-12-12 13:09:19

标签: c# generics

我正在尝试在mvvm模式中制作图片galerie。视图模型应该具有IGalerieModel类型的模型,以便视图模型支持不同的模型类型,以防我想要创建包含其他图片的视图。

viewmodel看起来像这样:

GalerieViewModel<TView, TModel> 
    where: TView is Galerieview
    where: TModel is IGalerieModel

要从后面的代码调用方法到viewmodel,我需要转换datacontext。为此,我有一个DataContext属性。它的类型是:

GalerieViewModel<GalerieView, IGalerieModel>();

但是如果我尝试将DataContext强制转换为此类型,则返回null。 datacontext不是null我检查过它,它只是不能将它转换为viewModel类型。 为什么这个和任何人都有替代解决方案?

编辑: 一些相关的代码,我尝试转换datacontext。

private void MenuItem_Click(object sender, System.Windows.RoutedEventArgs e)
{
    var selectedItem = Images.SelectedItem as Image;
    if(selectedItem != null)
    {
         var datacontext = DataContext as GalerieViewModel<GalerieView, IGalerieModel>;
         datacontext?.RemoveImage(selectedItem);
    }
}

2 个答案:

答案 0 :(得分:0)

我建议在这种情况下使用继承。

我使用以下术语:

  • ViewModel 一个对象,它是由单个特定视图显示和/或使用的数据封装(包括双向和单向)。
    • 例如,如果您的系统有3个屏幕/窗口(LoginViewOrdersListViewOrderDetailView),则每个屏幕/窗口都有自己的ViewModel(LoginVM,{{1 },OrdersListVM)。
    • 如果您的应用程序是围绕单个大视图构建的(并且您的应用程序不允许多个视图实例),那么允许任何子视图具有嵌套/子ViewModel的单片ViewModel(使用事件绑定很有趣) ,不过!)
  • 模型一个商业域实体,其出处不是 ViewModel 的关注点。我认为将域实体对象直接暴露给视图进行渲染是有效的,因为它有助于DRY。在许多简单和平凡的情况下,您可以直接使用域实体对象作为ViewModel,假设您不需要双向绑定和数据传输。但在很多情况下,这是非常不合适的。
  • 查看系统的表示层,在此上下文中,我们特别引用OrderDetailVMSystem.Windows.Controls.Window的某个特定子类,它充当离散组件。
    • 另外,当正确实现MVVM时,可以将整个WPF层替换为某些其他表示/视图系统甚至整个运行时环境,例如WinForms或UWP(但不是整个ASP.NET MVC)有状态范式崩溃)。

在您的情况下,我假设System.Windows.Controls.Control业务域实体类型的接口,它通常包装/封装位图数据。我无法想出数据如何不同,但我会接受你的意见。

所以你有一个单一的视图IGalerieModel,我假设它是一个简单的GalerieView视图,它有一个轻量级的,只有视图逻辑的*.xaml CodeBehind文件。

因此,您的ViewModel应如下所示:

.cs

所以根本不需要在这里使用泛型。

如果您确实想使用泛型,因为系统中的其他地方有关于public class GalerieViewModel { public String WindowTitle { get; set; } public String WelcomeMessage { get; set; } public virtual ObservableCollection<IGalerieModel> Images { get; set; } } 集合中对象的确切类型的知识,您应该在通用子类中实现该功能:

Images

(请注意,您需要编写代码以使两个public class GalerieViewModel<TImage> where TImage : IGalerieModel { public new ObservableCollection<TImage> Images { get; set; } } 个集合保持同步,请注意ObservableCollectionObservableCollection<IGalerieModel>相比,它更接受输入作为输入 - 这在泛型中使用可变集合的缺点,以及ObservableCollection<TImage>在实践中如何工作)。

然后您可以像这样使用它(使用您的示例):

ObservableCollection

为方便起见,您可以添加一个强类型属性来获取private void MenuItem_Click(Object sender, RoutedEventArgs e) { IGalerieModel selectedItem = this.Images.SelectedItem as IGalerieModel ; if( selectedItem != null ) { GalerieViewModel viewModel = (GalerieViewModel)this.DataContext; viewModel.Images.Remove( selectedItem ); } } 中的ViewModel(这是可以的,因为View了解ViewModel,但ViewModel并不知道观点):

View

您可能希望继承protected GalerieViewModel ViewModel { get { return (GalerieViewModel)this.DataContext; } } private void MenuItem_Click(Object sender, RoutedEventArgs e) { IGalerieModel selectedItem = this.Images.SelectedItem as IGalerieModel; if( selectedItem != null ) { this.ViewModel.Images.Remove( selectedItem ); } } 以添加强类型的ViewModel支持:

Window

答案 1 :(得分:0)

GalerieViewModel<GalerieView, SomeModel>GalerieViewModel<GalerieView, IGalerieModel>是两种完全独立的类型,无法投放。

实施SomeModel

IGalerieModel不会传播出通用。