【问题标题】:Is this a good way of using ViewModelLocator in MVVM这是在 MVVM 中使用 ViewModelLocator 的好方法吗
【发布时间】:2013-11-20 06:14:22
【问题描述】:

我们的 Silverlight 应用中有一个 ViewModelLocater 类。它由一个基本构造函数和一个用于返回类的 ViewModel 的公共属性组成。代码是这样的

public class ViewModelLocator
{
    private  Dictionary<string, ViewModel> _viewModels =
              new Dictionary<string, ViewModel>();

    public ViewModelLocator()
    {
        _viewModels.Add("Home",  HomeViewModel());
        _viewModels.Add("Setup", new SetupViewModel());
        _viewModels.Add("TasksActivities", new TasksActivitiesViewModel());
        _viewModels.Add("Timesheet", new TimesheetViewModel());
    }

    public ViewModel this[string viewName]
    {
        get { return _viewModels[viewName]; }
    }
}

在每个 XAML 页面中,我们使用

为该页面设置 ViewModel
DataContext="{Binding [Setup], Source={StaticResource ViewModelLocator}}"

Setup 是上述字典中的键。

Silverlight 应用程序非常大,我们最近才开始调查任何内存泄漏(有很多......)我正在使用 Windbg 来跟踪这些泄漏,我注意到很多内存泄漏导致 ViewModelLocater班级。每次应用加载 ViewModelLocator 构造函数时,都会为所有视图创建 ViewModel。所以我想知道是否有更好的方法来实现 ViewModelLocator 类。

【问题讨论】:

  • 你不能懒惰地创建视图模型(在需要时),而不是预先创建所有?
  • 创建 ViewModelLocater 类是为了在设计时提供一个虚拟模型。每个视图在其 OnNavigatedTo 事件中创建其视图模型的新实例。现在我是 MVVM 和 Silverlight 的新手,这个 ViewModellocater 类是由以前的高级程序员创建的。所以我不确定这是否是创建一个的正确方法。
  • 我们使用 ViewModelLoader/ViewModelLocator 来提供 DesignTime 和 Runtime DataContexts。我们的 ViewModelLoader 代码看起来像 this,我们所有的 ViewModelFactories 都将实现 IFactory,通过这种方式,您只是在需要时创建 ViewModel,而不是全部预先创建。
  • 你能给我举个例子吗?
  • 示例代码太大,无法作为评论发布,因此作为答案发布。

标签: silverlight xaml mvvm viewmodellocator


【解决方案1】:

我们使用 ViewModelLoader/ViewModelLocator 来提供 DesignTime 和 Runtime DataContexts。

ViewModelLocator 类

public static class ViewModelLocator
{
    public static readonly DependencyProperty FactoryProperty = DependencyProperty.RegisterAttached("Factory",
        typeof (IViewModelFactory), typeof (ViewModelLocator),
        new FrameworkPropertyMetadata(null, PropertyChangedCallback));

    public static void SetFactory(DependencyObject dependencyObject, IViewModelFactory value)
    {
        dependencyObject.SetValue(FactoryProperty, value);
    }

    public static IViewModelFactory GetFactory(DependencyObject dependencyObject)
    {
        return (IViewModelFactory) dependencyObject.GetValue(FactoryProperty);
    }

    private static void PropertyChangedCallback(DependencyObject dependencyObject,
        DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        var fe = dependencyObject as FrameworkElement;
        if (fe != null)
        {
            fe.DataContext = GetFactory(dependencyObject).Create();
        }
    }
}

IViewModelFactory

public interface IViewModelFactory
{
    object Create();
}

ViewModelFactory

public class MainViewModelFactory : ViewModelFactoryBase
{
    protected override object CreateDesignTimeViewModel()
    {
        return new MainViewModel(new DesignTimeEventAggregator(), new DesignTimeLogger(), new ViewModelViewRepository());
    }

    protected override object CreateViewModel()
    {
        return ServiceLocator.Current.GetInstance<MainViewModel>();
    }
}

ViewModelFactoryBase 类

public abstract class ViewModelFactoryBase : IViewModelFactory
{
    protected abstract object CreateDesignTimeViewModel();

    protected abstract object CreateViewModel();

    public object Create()
    {
        return Designer.IsInDesignTime() ? CreateDesignTimeViewModel() : CreateViewModel();
    }
}

在 XAML 中,这就是我将 ViewModel Locator 连接到 View 的方式:

<viewModelLocation:ViewModelLocator.Factory>
    <viewModelFactories:MainViewModelFactory />
</viewModelLocation:ViewModelLocator.Factory>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-22
    • 2012-06-02
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多