2

我是 PRISM 的新手,正在尝试一些事情。我在 MVVM 上有点挣扎。

将视图与视图模型“连接”的方式很明确:

  • 通过统一注入,或

  • 手动设置数据上下文 (ServiceLocator)

如果我将视图添加到区域(视图模型是自动创建的),一切正常。但这不是用例。

让我们看一下这个例子:

public class MyViewModel : NotificationObject
{
   public ObservableCollection<AnotherViewModel> OrderModel { get; private set; }
}

我必须创建视图模型并将它们添加到集合中。此视图模型必须在区域 (OrderRegion) 中显示 (AnotherView)。我的问题是,当我将视图模型添加到区域时,现在如何创建视图。该区域是一个 TabControl,因此可能会发生必须显示不同视图的情况。

我已经查看了 PRISM 快速入门和 StockTrader 示例。我正在寻找的是非常相似的

 virtual protected void StartOrder(string tickerSymbol, TransactionType transactionType)
    {
        if (String.IsNullOrEmpty(tickerSymbol))
        {
            throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.StringCannotBeNullOrEmpty, "tickerSymbol"));
        }
        this.ShowOrdersView();

        IRegion ordersRegion = _regionManager.Regions[RegionNames.OrdersRegion];

        var orderCompositeViewModel = ServiceLocator.Current.GetInstance<IOrderCompositeViewModel>();

        orderCompositeViewModel.TransactionInfo = new TransactionInfo(tickerSymbol, transactionType);
        orderCompositeViewModel.CloseViewRequested += delegate
        {
            OrderModels.Remove(orderCompositeViewModel);
            commandProxy.SubmitAllOrdersCommand.UnregisterCommand(orderCompositeViewModel.SubmitCommand);
            commandProxy.CancelAllOrdersCommand.UnregisterCommand(orderCompositeViewModel.CancelCommand);
            commandProxy.SubmitOrderCommand.UnregisterCommand(orderCompositeViewModel.SubmitCommand);
            commandProxy.CancelOrderCommand.UnregisterCommand(orderCompositeViewModel.CancelCommand);
            ordersRegion.Remove(orderCompositeViewModel);
            if (ordersRegion.Views.Count() == 0)
            {
                this.RemoveOrdersView();
            }
        };

        ordersRegion.Add(orderCompositeViewModel);
        OrderModels.Add(orderCompositeViewModel);

        commandProxy.SubmitAllOrdersCommand.RegisterCommand(orderCompositeViewModel.SubmitCommand);
        commandProxy.CancelAllOrdersCommand.RegisterCommand(orderCompositeViewModel.CancelCommand);
        commandProxy.SubmitOrderCommand.RegisterCommand(orderCompositeViewModel.SubmitCommand);
        commandProxy.CancelOrderCommand.RegisterCommand(orderCompositeViewModel.CancelCommand);

        ordersRegion.Activate(orderCompositeViewModel);
    }

视图模型在代码内部创建并添加到区域中。整个类型 regestring 是通过“ViewExportAttribute”发生的,因此更难理解其背后的模式。

编辑:

我找到了一种手动执行此操作的方法,但它不是很好:

var view = (FrameworkElement) ServiceLocator.Current.GetInstance<AnotherView>();
var model = ServiceLocator.Current.GetInstance<AnotherViewModel>();
view.DataContext = model;

regionManager.Regions["OrderRegion"].Add(view, null, true);
regionManager.Regions["OrderRegion"].Activate(view);

罗马

编辑2:

嗨,对不起,我可能不够清楚。

我的目标是创建一个视图模型,然后像上面的 StockTrader 示例中那样对其进行配置:订阅事件、命令等。之后我想将此视图模型添加到该区域,以便它可以显示。该区域可能是一个选项卡控件,其中显示具有不同视图模型的不同视图。顺序是:

  1. 在控制器类中创建视图模型
  2. 配置视图模型
  3. 将视图模型添加到控制器内的本地集合
  4. 将视图模型添加到区域

我一直在寻找的缺失部分是如何实现它,即视图是使用绑定等所有内容“自动”创建的。我在本文中找到了一种方法(http://www.codeproject.com/Articles /229931/了解-MVVM-Using-PRISM-by-Hello-World-Silverl)。我必须为视图和视图模型(IAnotherViewModel、IAnotherView)创建自己的接口。

另一种方法可以在这里找到:http: //paulstovell.com/blog/viewmodel-first-prism

4

2 回答 2

4

有什么理由不为此使用隐式DataTemplates

它们DataTemplates定义了一个DataType属性,但不是一个Key属性,并且在 WPF 尝试绘制指定 DataType 的对象时使用它们

例如,

<TabControl ItemsSource="{Binding MyViewModelCollection}"
            SelectedItem="{Binding SelectedViewModel}">
    <!-- This could also go elsewhere, like Application.Resources -->
    <TabControl.Resources>
        <DataTemplate DataType="{x:Type local:ViewModelA}">
            <local:ViewA />
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:ViewModelB}">
            <local:ViewB />
        </DataTemplate>
    </TabControl.Resources>
</TabControl>

如果TabControl正在显示类型的对象ViewModelA,它将使用 绘制它ViewA,如果它正在显示ViewModelB,它将使用绘制它ViewB

于 2013-04-10T13:35:14.853 回答
0

如果您使用的是 MEF,那么您可以使用属性自动注册视图:

/*YOUR VIEW*/
    [ExportViewToRegion("MyView", "MyRegion")]
        [Export(typeof(MyView))]
        public partial class MyView : UserControl
        { 
         ....
        }


/*IMPLEMENTATION*/

   public interface IExportViewToRegionMetadata
    {
         string ViewName { get; }
         string TargetRegion { get; }
    }

    [MetadataAttribute]
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = false)]
    public class ExportViewToRegionAttribute : ExportAttribute
    {
        public ExportViewToRegionAttribute(string viewName, string targetRegion)
            : base(typeof(UserControl))
        {
            ViewName = viewName;
            TargetRegion = targetRegion;
        }


        public string ViewName { get; private set; }
        public string TargetRegion { get; private set; }
    }


    [Export(typeof(IFluentRegionManager))]
    public class FluentRegionManager : IFluentRegionManager, IPartImportsSatisfiedNotification
    {
        public IRegionManager RegionManager { get; set; }

        [ImportingConstructor]
        public FluentRegionManager(IRegionManager regionManager)
        {
            RegionManager = regionManager;
        }


        /*This Import will find all views in the assembly with attribute [ExportViewToRegion("ViewName", "RegionName")]*/
        [ImportMany(AllowRecomposition = true)]
        public Lazy<UserControl, IExportViewToRegionMetadata>[] Views { get; set; }



        private readonly List<string> _processedViews = new List<string>();

        private Lazy<UserControl, IExportViewToRegionMetadata> _GetViewInfo(string viewName)
        {
            return (from v in Views where v.Metadata.ViewTypeForRegion.Equals(viewName) select v).FirstOrDefault();
        }

        public IExportViewToRegionMetadata this[string viewName]
        {
            get
            {
                return (from v in Views
                        where v.Metadata.ViewName.Equals(viewName, StringComparison.InvariantCultureIgnoreCase)
                        select v.Metadata).FirstOrDefault();
            }
        }

        public void ExportViewToRegion(string viewName)
        {

            if (viewName==null)
            {
                throw new ArgumentNullException("viewName");
            }

            var viewInfo = _GetViewInfo(viewName);

            string targetRegion;
            UserControl _view;

            if (viewInfo != null)
            {
                targetRegion = viewInfo.Metadata.TargetRegion;
                _view = viewInfo.Value;
            }


            if (string.IsNullOrEmpty(targetRegion) || _processedViews.Contains(viewName)) return;

            RegionManager.RegisterViewWithRegion(targetRegion,  _view.GetType());
            _processedViews.Add(viewName);
        }


        /*All required views has been discovered and imported */
        /*Loop true collection and register view with the region */
        public void OnImportsSatisfied()
        {
            foreach (var viewName in  from view in Views where !_processedViews.Contains(view.Metadata.ViewName) 
                select view.Metadata.ViewName)
            {
                ExportViewToRegion(viewName);
            }
        }
    }

/* finally call IFluentRegionManager import in the bootstrapper to kick off registration*/
于 2013-10-17T12:32:44.700 回答