【问题标题】:MVVM Light, Metro App, Inheriting ViewModelBase breaks design modeMVVM Light, Metro App, Inheriting ViewModelBase 打破设计模式
【发布时间】:2013-04-17 20:24:52
【问题描述】:

我遇到了一个奇怪的问题,我似乎找不到任何答案。

我正在使用 Visual Studio 2012 通过 NuGet 使用 MVVM Light 构建 Metro Store 应用程序。

在设计和添加数据上下文 xaml 代码时,studio 给了我一个红色的 swiggly 错误“对象引用未设置为对象的实例”。

DataContext={Binding MainVM, Source={StaticResource Locator}}

我终于把它缩小到我的视图模型中的继承。我有一个基本视图模型,我的所有视图模型都继承自声明如下:

public class BaseViewModel : ViewModelBase
{
}

那么显然我所有的视图模型都是这样的:

public class MainViewModel : BaseViewModel
{
}

现在,在运行时一切正常(这让我很困惑),但是设计模式中断了。

但是,如果我删除继承并让我的视图模型直接继承 ViewModelBase,那么在设计模式下一切都很好:

public class MainViewModel : ViewModelBase
{
}

我认为可能是代码中的某些问题导致了问题,因此我将所有内容都注释掉了,除了编译所需的内容并仍然收到相同的结果。

有人似乎有这个问题,或者知道我可能做错了什么吗?在使用 MVVM 处理 Silverlight 或 WPF 应用程序时,我通常使用相同的模式,那里的情况似乎很好。

顺便说一句,我的 ViewModelLocator 确实有一个返回 MainViewModel 类的 MainVM 属性。

更新 在阅读了 LBugnion 和 Will 的 cmets 之后,我正准备调试设计模式时发现我愚蠢地忘记在 BaseViewModel 中注释掉我的代码。我确实发现那里有破坏代码。设计模式不喜欢下面这行:

private CoreDispatcher UIDispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;

我用来更新代码中的 UI 线程。我猜(有经验的人可能会插话)设计模式下没有 UI 线程?

通常我使用“IsInDesignMode”属性使我的视图模型几乎无法用于设计,但显然在这里忘记了这样做,所以我将上面的行更改为

private CoreDispatcher UIDispatcher = IsInDesignModeStatic ? null : Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;

我的笨蛋

【问题讨论】:

  • 我经常这样做,因此通常仅此一项就不会破坏设计模式。一定是某处抛出了异常,有没有尝试调试设计模式代码?
  • 没错,我通常对其他技术也这样做,所以我想这可能是 Metro 的事情。显然我错了,我搞砸了我的调试(如上面的更新中所述),所以谢天谢地,现在一切正常。谢谢!

标签: xaml mvvm microsoft-metro windows-store-apps mvvm-light


【解决方案1】:

一直在发生,主要是因为您的类型中的代码正在设计器中执行。

是的,代码实际上可以在设计器中执行。设计器会将您的程序集加载到设计图面的 AppDomain 中,实例化您的类型,并将该实例用于设计图面。

因此,如果你有这样的事情:

public MyView : UIElement
{
    public MyView()
    {
        InitializeComponent();
        var database = GetDatabaseObject();
        database.OpenLikeWeAreInProduction();
        FillTheUiLol(database.GetAllKindsOfCrap());
    }
}

它很可能会因为您的数据库不存在而中断,您无法从 app.config 等中找到连接字符串等。

处理这种情况的方法是,只要您有可能在设计器中执行的代码(例如在构造函数中、在属性更改事件处理程序中等),您应该使用DesignerProperties.GetInDesignMode(new DependencyObject()) 来确定您是否在设计器在执行代码之前保证会中断设计器。

不幸的是,有时很难确定什么代码正在破坏。对于难以推断的故障,我唯一的解决方案是记下异常类型,启动另一个 Visual Studio 实例,附加到第一个实例,然后将调试配置为始终中断该异常类型。

【讨论】:

  • 给你答案打勾 Will 因为你给的方法是在这种情况下帮助调试的好方法。如果我还没有发现问题,我相信我会使用这个解决方案找到问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 2017-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-31
  • 1970-01-01
  • 2012-01-11
相关资源
最近更新 更多