让 Unity 解析 XAML 中的视图

发布于 2024-08-11 08:14:04 字数 473 浏览 12 评论 0原文

我开始使用 MVVM,并且开始理解一些事情。我目前正在尝试 Cinch 框架,尽管我还没有致力于它。
我通过在视图的代码隐藏中引用 ViewModel 将 ViewModel 注入到视图中,该属性具有 [Dependency],并在 setter 中使用 Unity 将 DataContext 设置为正确的视图。我想,这真是绝妙的把戏。

我试图让我的应用程序作为单个窗口工作,并带有注入的视图(而不是多个窗口并处理打开\关闭它们) 我将视图从 Windows 更改为 UserControls,并向主窗口添加了 。 这有效,但 ViewModel 从未被注入,大概是因为 XAML 不使用 Container.Resolve 创建视图,因为当我创建视图并使用 Resolve 在代码隐藏中手动添加它时,创建了 [Dependency] 。

我如何设置我的窗口,以便如果我通过 XAML 添加视图,或者视图由于 UI 操作等而发生更改,它可以通过 Unity 获取它,以便它可以发挥其魔力?

I'm starting out with MVVM, and I'm starting to understand things. I'm currently experimenting with the Cinch framework, though I'm not committed to it as of yet.
I was injecting the ViewModels into the Views using by having a reference to the ViewModel in the codebehind of the view, with the property having a [Dependency] on it, and in the setter it sets the DataContext to the right view, using Unity. Neat trick, I thought.

I'm trying to get my app to work as a single Window, with injected views (As opposed to multiple windows and dealing with opening\closing them)
I changed my views from Windows to UserControls, and added a to the main window.
That worked, but the ViewModel was never injected, presumably because the XAML doesn't use Container.Resolve to create the view, as when I created the view and added it manually in the code-behind using Resolve, the [Dependency] was created.

How can I set up my window, so that if I add a view through XAML, or the view gets changed as a result of a UI action etc, it gets it through Unity, so that it can work its magic?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

遮云壑 2024-08-18 08:14:04

这个问题通常可以使用 Regions 和 RegionManager 来解决。在主窗口 ViewModel 中,创建一组 Region 并将其添加到 RegionManager 中。然后可以解析 ViewModel 并将其添加到 Region.Views 集合中。

在 XAML 中,通常通过将 ItemsControl 的 ItemsSource 属性绑定到主 ViewModel 的 Region 属性来注入 Region。

因此,在主屏幕 ViewModel 中,您将看到如下所示的内容:

    public class TestScreenViewModel
{
    public const string MainRegionKey = "TestScreenViewModel.MainRegion";

    public TestScreenViewModel(IUnityContainer container, IRegionManager regionManager)
    {
        this.MainRegion = new Region();
        regionManager.Regions.Add(MainRegionKey, this.MainRegion);
    }

    public Region MainRegion { get; set; }
}

This will be Resolved平时在您的 IModule 中

        #region IModule Members

    public void Initialize()
    {
        RegisterViewsAndServices();

        var vm = Container.Resolve<SelectorViewModel>();
        var mainScreen = Container.Resolve<TestScreenViewModel>();
        mainScreen.MainRegion.Add(vm);

        var mainView = ContentManager.AddContentView("Test harness", mainScreen);
    }

    #endregion

并且模板的 XAML 表示看起来像这样

    <DataTemplate DataType="{x:Type TestModule:TestScreenViewModel}">
    <ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Auto">
        <StackPanel>
            <ItemsControl ItemsSource="{Binding Path=MainRegion.Views}" />
        </StackPanel>
    </ScrollViewer>
</DataTemplate>

This problem is normally solved using Regions and the RegionManager. In the main window ViewModel, a set of Regions is created and added to the RegionManager. Then ViewModels can be Resolved and added to the Region.Views collection.

In XAML, the Region is normally injected by having the ItemsSource property of an ItemsControl bound to the region property of the main ViewModel.

So, in the main screen ViewModel you would have something like this:

    public class TestScreenViewModel
{
    public const string MainRegionKey = "TestScreenViewModel.MainRegion";

    public TestScreenViewModel(IUnityContainer container, IRegionManager regionManager)
    {
        this.MainRegion = new Region();
        regionManager.Regions.Add(MainRegionKey, this.MainRegion);
    }

    public Region MainRegion { get; set; }
}

This would be Resolved normally in your IModule

        #region IModule Members

    public void Initialize()
    {
        RegisterViewsAndServices();

        var vm = Container.Resolve<SelectorViewModel>();
        var mainScreen = Container.Resolve<TestScreenViewModel>();
        mainScreen.MainRegion.Add(vm);

        var mainView = ContentManager.AddContentView("Test harness", mainScreen);
    }

    #endregion

And the XAML representation of your template looking something like

    <DataTemplate DataType="{x:Type TestModule:TestScreenViewModel}">
    <ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Auto">
        <StackPanel>
            <ItemsControl ItemsSource="{Binding Path=MainRegion.Views}" />
        </StackPanel>
    </ScrollViewer>
</DataTemplate>
三月梨花 2024-08-18 08:14:04

解决问题的方法是让您的窗口也有一个 ViewModel,并将 UserControls 的 ViewModel 作为属性公开。然后,在窗口的 XAML 中,您只需使用绑定机制将 UserControl 的 DataContext 绑定到主 ViewModel 的正确属性。由于该主 ViewModel 是从 Unity 容器解析的,因此它将根据需要注入所有其他 ViewModel。

The way to solve your problem is to make your window to have a ViewModel as well, with ViewModels of UserControls exposes as properties on it. Then in your XAML for a window you'd simply use Binding mechanism to bind UserControl's DataContexts to proper properties of your your main ViewModel. And since that main ViewModel is resolved from Unity container it would have all other ViewModel-s injected as needed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文