c# - 命名空间自定义约定 - View 和 View 模型位于单独的程序集中

标签 c# namespaces viewmodel caliburn.micro

我在名为 MyApp.Shell 的单个程序集中有 ShellView 和 ShellViewModel。

View 模型:

namespace MyApp.Shell.ViewModels
{
    public class ShellViewModel : Conductor<IScreen>.Collection.AllActive, IShellViewModel
    {
        public IMenuViewModel Menu { get; set; }

    }
}

查看:

namespace MyApp.Shell.Views
{
    /// <summary>
    /// Interaction logic for ShellView.xaml
    /// </summary>
    public partial class ShellView : Window
    {
        public ShellView()
        {
            InitializeComponent();
        }
    }
}

在另一个名为 MyApp.MenuViewModel 的程序集中,我有部分 MenuViewModel。

namespace MyApp.MenuViewModel.ViewModels
{
    public class MenuViewModel : Screen, IMenuViewModel
    {

    }
}

在名为 MyApp.MenuView 的第三个程序集中,我有部分 MenuView。

namespace MyApp.MenuView.Views
{
    /// <summary>
    /// Interaction logic for MenuView.xaml
    /// </summary>
    public partial class MenuView : UserControl
    {
        public MenuView()
        {
            InitializeComponent();
        }
    }
}

我想从 ShellView 中的程序集 MyApp.MenuView 加载 MenuView。

<Window x:Class="MyApp.Shell.Views.ShellView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ShellView" Height="600" Width="1000">
    <Grid ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition x:Name="rowMenu" Height="25"/>
        </Grid.RowDefinitions>


        <ContentControl x:Name="Menu" Grid.Row="0"/>


    </Grid>
</Window>

因为命名空间不一样,我在 Bootstrap 中的配置方法中尝试了映射命名空间:

我的目标是翻译 namespace MyApp.MenuView.Views -> MyApp.Shell.Views

 ViewLocator.AddSubNamespaceMapping("MyApp.*.Views", "Shell");

并翻译命名空间 MyApp.MenuViewModel.ViewModels -> MyApp.Shell.ViewModels

ViewModelLocator.AddSubNamespaceMapping("MyApp.*.ViewModels", "Shell");

但是当我运行应用程序时出现错误:

找不到 MyApp.MenuViewModel.ViewModels 的 View 。菜单 View 模型

我也尝试过这个

        ViewLocator.AddNamespaceMapping("MyApp.*.Views", "MyApp.Shell.Views");

        ViewModelLocator.AddNamespaceMapping("MyApp.*.ViewModels", "MyApp.Shell.ViewModels");

出了什么问题?问题出在 AddSubNamespaceMapping/AddNamespaceMapping 方法中,还是这个问题的根源在其他地方?

因为如果我将程序集 MyApp.MenuView 中的 namespace MyApp.MenuView.Views 更改为 MyApp.Shell.Views ,一切都会正常。

谢谢

这是 Bootstrap :

也许我在错误的地方使用了 AddSubNamespaceMapping。

public class CWBootstrapper : Bootstrapper<IShellViewModel>
    {
        #region Fields

        private IWindsorContainer _container;

        #endregion

        #region Methods

        private IEnumerable<Assembly> LoadAssemblies(string folder)
        {
            var directory = new DirectoryInfo(folder);
            FileInfo[] files = directory.GetFiles("*.dll", SearchOption.TopDirectoryOnly);

            foreach (FileInfo file in files)
            {
                AssemblyName assemblyName = AssemblyName.GetAssemblyName(file.FullName);
                Assembly assembly = AppDomain.CurrentDomain.Load(assemblyName);//Assembly.Load(assemblyName);
                yield return assembly;
            }

            yield break;
        }

        protected override void Configure()
        {
            _container = new WindsorContainer();

            _container.Register(Component
                                .For<IWindowManager>()
                                .ImplementedBy<WindowManager>()
                                .LifeStyle.Is(LifestyleType.Singleton));

            _container.Register(Component
                                .For<IEventAggregator>()
                                .ImplementedBy<EventAggregator>()
                                .LifeStyle.Is(LifestyleType.Singleton));


            _container.Install(new ViewModelsInstaller());
            _container.Install(new ViewsInstaller());


            //MyApp.MenuView.Views
            ViewLocator.AddSubNamespaceMapping("MyApp.*.Views", "Shell");
            //MyApp.MenuViewModel.ViewModels
            ViewModelLocator.AddSubNamespaceMapping("MyApp.*.ViewModels", "Shell");

            var config = new TypeMappingConfiguration
            {

                DefaultSubNamespaceForViews = "MyApp.Shell.Views",
                DefaultSubNamespaceForViewModels = "MyApp.Shell.ViewModels",

                ViewModelSuffix = "ViewModel",
                ViewSuffixList = new List<string> { "View" }
            };

            ViewLocator.ConfigureTypeMappings(config);
            ViewModelLocator.ConfigureTypeMappings(config);

        }


        protected override IEnumerable<Assembly> SelectAssemblies()
        {
            var assemblies = base.SelectAssemblies().ToList();

    //load views asm from folder Views
            IEnumerable<Assembly> viewsAsm = LoadAssemblies(@"Views");
    //load viewmodels asm from folder ViewModel
            IEnumerable<Assembly> viewModelsAsm = LoadAssemblies(@"ViewModels");

            assemblies.AddRange(viewsAsm);
            assemblies.AddRange(viewModelsAsm);

            return assemblies;
        }

        protected override object GetInstance(Type service, string key)
        {
            return string.IsNullOrWhiteSpace(key)
                       ? _container.Resolve(service)
                       : _container.Resolve(key, new { });
        }

        protected override IEnumerable<object> GetAllInstances(Type service)
        {
            return _container.ResolveAll(service).Cast<object>();
        }

        protected override void BuildUp(object instance)
        {
            instance.GetType().GetProperties()
                .Where(property => property.CanWrite && property.PropertyType.IsPublic)
                .Where(property => _container.Kernel.HasComponent(property.PropertyType))
                .ForEach(property => property.SetValue(instance, _container.Resolve(property.PropertyType), null));
        }

        #endregion
    }

编辑:

我在这里上传我的解决方案:http://www.4shared.com/rar/yaPwUV6d/App.html

有人可以帮助我吗?我找不到问题所在。

最佳答案

好吧,Kopernik,你的问题让我读到了很多我搁置的信息。不过,您的问题可以通过一行代码解决:

ViewLocator.AddSubNamespaceMapping("MyApp.MenuViewModel.ViewModels", "MyApp.MenuView.Views");

如果这不能单独工作,那么确保您添加/加载包含 View 的程序集(在您的情况下是MyApp.MenuView )SelectAssemblies() 覆盖中正确地转换为 AssemblySource.Instance

您的问题背后的基本思想是 Caliburn.Micro 的 ViewLocator 正在寻找 MyApp.MenuViewModel.ViewModels.MenuViewMyApp.MenuViewModel.Views。 MenuView 但找不到其中任何一个。

本质上,我所做的就是告诉 Caliburn.Micro 的 ViewLocator 在需要时用 MyApp.MenuView.Views 替换 MyApp.MenuViewModel.ViewModels寻找风景和wallah!它找到了。

从我从您的代码中可以看出,您似乎正在执行 View 模型优先导航,因此您暂时不需要任何其他内容。

最后一件事,对问题的彻底解释以及如何解决它可能需要大量解释,但我真的没有时间,所以我建议您阅读 NameTransformerViewModel/View Naming Conventions文章来对此有一个很好的了解。

关于c# - 命名空间自定义约定 - View 和 View 模型位于单独的程序集中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17755242/

相关文章:

Android ViewModel 观察 Mu​​tableLiveData<ArrayList<String>>

c# - 控制台应用程序中 WCF 托管服务中的 MaxReceivedMessageSize

c# - 看不到其他文本框

mvvm - 如何将数据(选定项目)传递给 Durandal 组合详细 View ?

reactjs - Hook useTranslation() 不读取导入的命名空间 - i18next

xml - 使用带有命名空间的正确路径来解析 XML(在 VBA 中)

asp.net-mvc - 维护ASP.NET MVC中复选框动态列表的状态

c# - 在ABP中从CrudAppService检索子实体

c# - C# 中的日期时间格式

C# 从 LinQ XDocument 加载数据表