【问题标题】:Getting Silverlight MVVM working with Expression Blend design time data?让 Silverlight MVVM 与 Expression Blend 设计时数据一起工作?
【发布时间】:2011-03-22 07:43:39
【问题描述】:

我是 Silverlight 的 MVVM 模式的大力支持者。目前,我通过在视图后面的代码中新建 ViewModel 将 ViewModel 连接到视图,因此:

public partial class SomePage : UserControl
{
    public SomePage()
    {
        InitializeComponent();

        // New up a ViewModel and bind to layout root
        var vm = new SomeViewModel();
        LayoutRoot.DataContext = vm;
    }
}

然后所有的绑定都在 View 中处理,所有的逻辑都在 ViewModel 中处理,正如模式所希望的那样。

但是,以这种方式连接它们意味着设计器无法正常工作,并且我无法使用 Expression Blend 设计时数据。我知道有诸如 MVVM Light 之类的库可以帮助完成所有这些工作,但我不喜欢引入库,因为它是“需要处理的“另一件事”。

是否有一种简单的模式可以在 Silverlight 中连接 MVVM,同时保持设计器功能,尤其是在 Blend 中?我已经进行了一些谷歌搜索,但是那里有太多过时的文章,并且 WPF 和 Silverlight 以及旧版本之间存在太多混淆,以至于我很难弄清楚该使用哪个。

顺便说一句,如果重要的话,我会专注于带有 VS2010 的 SL4。

【问题讨论】:

    标签: silverlight mvvm silverlight-4.0


    【解决方案1】:

    您可以使用几种方法。

    首先,让 Expression 的示例数据和设计时属性(即 d:DataContext)接管设计器。在您的代码中,您只需调整视图模型绑定:

    if (!DesignerProperties.IsInDesignTool)
    {
       var vm = new SomeViewModel();
       LayoutRoot.DataContext = vm; 
    }
    

    第二,您可以拥有一个特殊的设计时视图模型来代替:

    LayoutRoot.DataContext = DesignerProperties.IsInDesignTool ?
        new DesignViewModel() : new MyViewModel(); 
    

    最后,另一种方法是在视图模型中管理数据。我不喜欢这样,因为它会将责任分散到所有视图模型中,但您可以更精确:

    // constructor
    private Widget[] _designData = new[] { new Widget("Test One"), new Widget("Test Two") };
    
    public MyViewModel()
    {
       if (DesignerProperties.IsInDesignTool)
       {
           MyCollection = new ObservableCollection<Widget>(_designData);       
       }
       else 
       {
           MyService.Completed += MyServiceCompleted;
           MyService.RequestWidgets();
       }
    }
    
    private void MyServiceCompleted(object sender, AsynchronousEventArgs ae)
    {
       // load up the collection here
    }
    

    希望有帮助!

    【讨论】:

    • 嗯...所有这些方法都值得进行一些实验。感谢您的反馈。您能否提供有关第一种方法的更多详细信息?是否有一些我可以阅读的文档或博客文章?
    • 当然。我在这里构建的参考 Silverlight 应用程序中广泛使用了设计时属性:csharperimage.jeremylikness.com/2010/06/…
    【解决方案2】:

    您正在寻找的是“混合性”。 MVVM Light 有一个 ViewModelLocator 的概念,我在一个项目中使用它,效果很好。

    这是Roboblob 关于该主题的精彩帖子。 http://blog.roboblob.com/2010/01/17/wiring-up-view-and-viewmodel-in-mvvm-and-silverlight-4-blendability-included/ 这篇文章有一个示例解决方案,因此它确实有助于理解。 Rob 改进了 MVVM Light 实现,我认为做得很好。

    【讨论】:

      【解决方案3】:

      我在设计 WPF 应用程序时遇到过类似的问题。我学到的一个技巧是声明一个 xmlns,这样您就可以在 XAML 中嵌入一组对象:

      xmlns:coll="clr-namespace:System.Collections;assembly=mscorlib"
      

      然后,您可以将任何内容的 ArrayList 放入 XAML:

      <coll:ArrayList x:Key="questions">
          <local:QuestionItem Title="FOO"></local:QuestionItem>
      </coll:ArrayList>
      

      然后您可以将网格、列表框等的 ItemsSource 设置为数组:

      <ListBox x:Name="lstStuff" ItemsSource="{StaticResource questions}" />
      

      此技术将允许您在设计器中“预览”列表样式控件的外观。它并不能解决视觉原型设计的所有问题,但它有很长的路要走,可以适应几种不同的场景。

      例如,您可以将本地命名空间声明为 xmlns,然后将 ViewModel 的模拟拖放到窗口或控件的资源中。我没有尝试过,但理论上你可以获得完整的设计时预览。

      【讨论】:

      • 所以在您的示例中,您会在运行时将 lstStuff 的 ItemsSource 设置为其他值吗?你会在代码隐藏中这样做吗?
      • 我通常在测试/原型设计时在 XAML 中设置 ItemsSource,然后删除 ItemsSource 设置以测试应用程序。根据您填充列表控件的方式,可能需要也可能不需要删除 ItemsSource 设置
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多