【问题标题】:MEF - Adding view to the shell region doesn't inject viewModel into view usingMEF - 将视图添加到外壳区域不会使用 viewModel 将视图注入视图
【发布时间】:2015-02-24 20:06:49
【问题描述】:

我正在使用 Prism + MEF

我有相当简单的应用程序。 我有一个区域为“Region1”的外壳。 将模块作为单独的项目使用MyUserControl.xamlMyUserControlVM.csModuleA.cs。此用户控件必须显示在 Shell--> Region1 中。为此,我已将此用户控件添加到 ModuleA.cs 的区域中

现在MyUserControlVM 不会注入UserControl Datacontext

    [ModuleExport(typeof(ModuleA))]
    public class ModuleA : IModule
    {
        public void Initialize()
        {
            var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();

            regionManager.Regions["Region1"].Add(new MyUserControl());
        }
    }

MyuserControl.Xaml

<StackPanel>
    <Label Content="{Binding Message}" Height="38" HorizontalAlignment="Left" Name="label1" VerticalAlignment="Top" Width="193" Background="#FFD8CFCF" />
    <Label Content="ABC"></Label>
</StackPanel>

MyUserControl.Xaml.cs

public partial class MyUserControl : UserControl
    {
        public MyUserControl()
        {
            InitializeComponent();
        }

        [Import]
        public MyUserControlVM ViewModel
        {
          get { return this.DataContext as MyUserControlVM; }
          set { this.DataContext = value; }
       }        
   }

MyUserControlVM.cs

    [Export(typeof(MyUserControlVM))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class MyUserControlVM : INotifyPropertyChanged
    {
        private string _message;

        public string Message
        {
            get { return _message; }
            set
            {
                _message = value;
                NotifyPropertyChanged("Message");
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            if(PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

Shell.Xaml 中定义的区域:

<Grid>
    <ContentControl Name="Region1" regions:RegionManager.RegionName="Region1" Margin="70">
            </ContentControl>
</Grid>

App.xaml.cs 是这样的

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            var bootstrapper = new Bootstrapper();
            bootstrapper.Run();
        }

BootStrapper 是这样的

    public class Bootstrapper : MefBootstrapper
    {
        protected override DependencyObject CreateShell()
        {
            return Container.GetExportedValue<Shell>();
        }

        protected override void InitializeShell()
        {
            base.InitializeShell();
            App.Current.MainWindow = (Window)Shell;
            App.Current.MainWindow.Show();
        }

        protected override void ConfigureAggregateCatalog()
        {
            base.ConfigureAggregateCatalog();

            AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Shell).Assembly));
            AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(ModuleLibrary.ModuleA).Assembly));

        }

    }

请帮助我哪里做错了。

【问题讨论】:

    标签: c# wpf prism mef


    【解决方案1】:

    答案很简单。

    您显式创建视图的实例 (MyUserControl):

    regionManager.Regions["Region1"].Add(new MyUserControl());
    

    在这种情况下,MEF 不参与对象的生命周期。

    让 Prism 为您创建视图实例,以便 IoC 容器可以处理对象(包括部件组合和依赖注入):

    regionManager.RegisterViewWithRegion("Region1", typeof(MyUserControl));
    

    另外,我建议你避免使用ServiceLocator 反模式:

    ServiceLocator.Current.GetInstance<IRegionManager>();
    

    取而代之的是,使用依赖注入:

    [ModuleExport(typeof(ModuleA))]
    public class ModuleA : IModule
    {
        private readonly IRegionManager regionManager;
    
        [ImportingConstructor]
        public ModuleA(IRegionManager regionManager)
        {
            this.regionManager = regionManager;
        }
    
        public void Initialize()
        {
            this.regionManager.RegisterViewWithRegion("Region1", typeof(MyUserControl));
        }
    }
    

    【讨论】:

    • 谢谢!有一个问题我可以在引导程序中做类似于Container.GetExportedValue&lt;Shell&gt;();Container.GetExportedValue&lt;MyUserControl&gt;(); 吗?
    • @Babu,引导程序不打算创建用户特定的应用程序逻辑对象,所以最好不要这样做。您的UserControl 是一个视图,应该由 Prism 通过视图注册(RegisterViewWithRegion() 方法)或导航(regionManager.RequestNavigate("Region1", "UserControl"))创建。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多