C# PRISM:如何将视图模型添加到区域并自动创建视图?

C# PRISM:如何将视图模型添加到区域并自动创建视图?,c#,wpf,mvvm,prism,C#,Wpf,Mvvm,Prism,我对PRISM还不熟悉,还尝试了一些东西。我和MVVM有点纠结 将视图与viewmodel“连接”的方式很清楚: 通过统一注入,或 手动设置数据上下文(ServiceLocator) 如果我将视图添加到区域(viewmodel是自动创建的),则一切正常。但这不是用例 让我们来看一个例子: public class MyViewModel : NotificationObject { public ObservableCollection<AnotherViewModel>

我对PRISM还不熟悉,还尝试了一些东西。我和MVVM有点纠结

将视图与viewmodel“连接”的方式很清楚:

  • 通过统一注入,或

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

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

让我们来看一个例子:

public class MyViewModel : NotificationObject
{
   public ObservableCollection<AnotherViewModel> OrderModel { get; private set; }
}
公共类MyViewModel:NotificationObject { 我必须为视图和视图模型(iOnotherViewModel,iOnotherView)创建自己的接口


这里可以找到另一种方法:

是否有任何理由不为此使用隐式
数据模板

它们是定义
数据类型
属性的
数据模板
,但不是
属性,并且在WPF尝试绘制指定数据类型的对象时使用它们

比如说,

<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>


如果
选项卡控件
正在显示类型为
ViewModelA
的对象,它将使用
ViewModelA
进行绘制,如果它正在显示
ViewModelB
,它将使用
ViewB
进行绘制是否有任何理由不为此使用隐式
数据模板

它们是定义
数据类型
属性的
数据模板
,但不是
属性,并且在WPF尝试绘制指定数据类型的对象时使用它们

比如说,

<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>


如果
选项卡控件
正在显示类型为
ViewModelA
的对象,它将使用
ViewModelA
进行绘制,如果它正在显示
ViewModelB
,它将使用
ViewB

进行绘制。如果您正在使用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*/
/*您的视图*/
[ExportViewToRegion(“MyView”、“MyRegion”)]
[导出(typeof(MyView))]
公共部分类MyView:UserControl
{ 
....
}
/*实施*/
公共接口IExportViewToRegionMetadata
{
字符串ViewName{get;}
字符串TargetRegion{get;}
}
[元数据属性]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property,AllowMultiple=false)]
公共类ExportViewToRegionaAttribute:ExportAttribute
{
公共ExportViewToRegionaAttribute(字符串viewName、字符串targetRegion)
:base(typeof(UserControl))
{
ViewName=ViewName;
TargetRegion=TargetRegion;
}
公共字符串ViewName{get;private set;}
公共字符串TargetRegion{get;private set;}
}
[导出(类型(IFluentRegionManager))]
公共类FluentRegion管理器:iFluentRegion管理器、iPartimportsAssetFiedNotification
{
公共IRegionManager区域管理器{get;set;}
[导入构造函数]
公共FluentRegionManager(IRegionManager regionManager)
{
RegionManager=RegionManager;
}
/*此导入将查找具有属性[ExportViewToRegion(“ViewName”、“RegionName”)]的程序集中的所有视图*/
[进口数量(AllowRecomposition=true)]
公共惰性[]视图{get;set;}
私有只读列表_processedViews=new List();
private Lazy\u GetViewInfo(字符串viewName)
{
返回(从视图中的v返回,其中v.Metadata.ViewTypeForRegion.Equals(viewName)选择v).FirstOrDefault();
}
公共IExportViewToRegionMetadata此[字符串视图名称]
{
收到
{
返回(从视图中的v)
其中v.Metadata.ViewName.Equals(ViewName、StringComparison.InvariantCultureIgnoreCase)
选择v.Metadata).FirstOrDefault();
}
}
public void ExportViewToRegion(字符串viewName)
{
if(viewName==null)
{
抛出新的ArgumentNullException(“viewName”);
}
var viewInfo=_GetViewInfo(viewName);
字符串目标区域;
用户控制视图;
如果(视图信息!=null)
{
targetRegion=viewInfo.Metadata.targetRegion;
_视图=视图信息值;
}
if(string.IsNullOrEmpty(targetRegion)| | | u processedViews.Contains(viewName))返回;
RegionManager.RegisterViewWithRegion(targetRegion,_view.GetType());
_processedViews.Add(视图名称);
}
/*已发现并导入所有必需的视图*/
/*使用区域循环true集合和register视图*/
公共无效OnImportsAssetized()
{
foreach(视图中的from视图中的var viewName,其中!\u processedViews.Contains(view.Metadata.viewName)
选择view.Metadata.ViewName)
{
ExportViewToRegion(视图名称);
}
}
}
/*最后在引导程序中调用IFluentRegionManager导入以开始注册*/

如果您正在使用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*/
/*您的视图*/
[ExportViewToRegion(“MyView”、“MyRegion”)]
[导出(typeof(MyView))]
公共部分类MyView:UserControl
{ 
....
}
/*实施*/
公共接口IExportViewToRegionMetadata
{
字符串ViewName{get;}
字符串TargetRegion{get;}
}
[元数据属性]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property,AllowMultiple=false)]
公共类ExportViewToRegionaAttribute:ExportAttribute
{
公共出口vi