【问题标题】:WPF Caliburn.Micro and TabControl - changing tab, not changing modelWPF Caliburn.Micro 和 TabControl - 更改选项卡,不更改模型
【发布时间】:2017-07-30 21:43:57
【问题描述】:

我是 WPF&MVVM&Caliburn 的新手,所以我请求你的放纵 :)

我在将 TabControl 与动态创建的模型绑定时遇到问题。 Tabcontrol 正在正确创建,但更改选项卡不会切换用于绑定“视图”的视图模型(我使用的是视图模型第一种方法)

我已经根据这个问题提出了我的解决方案:WPF Caliburn.Micro and TabControl with UserControls issue

这是我的模型定义:

public interface IMainScreenTabItem : IScreen
{
}

public class MainViewTestTabsViewModel : Conductor<IMainScreenTabItem>.Collection.OneActive
{
    public MainViewTestTabsViewModel(IEnumerable<IMainScreenTabItem> tabs)
    {
        Items.Add(new ViewTabModel("Foo1"));
        Items.Add(new ViewTabModel("Foo2"));
        Items.AddRange(tabs);
    }
}

public sealed class ViewTabModel : Screen, IMainScreenTabItem
{
    public ViewTabModel(string displayName)
    {
        DisplayName = displayName;
    }
}

这里是 MainViewTestTabsView 视图:

<UserControl  x:Class="TestWpfApp.Views.MainViewTestTabsView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:TestWpfApp.Views"
    xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
    xmlns:viewModels="clr-namespace:TestWpfApp.ViewModels"
    xmlns:cal="http://www.caliburnproject.org"
    mc:Ignorable="d" Width="500" Height="500">
<Grid>
    <TabControl Name="Items">
        <TabControl.ContentTemplate>
            <DataTemplate>
                <StackPanel>
                    <Label  cal:Bind.Model="{Binding}" x:Name="DisplayName" Height="200" Width="200" />
                </StackPanel>
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>
</Grid>

我想要实现的 - 是让 TabControl 带有许多选项卡。每个选项卡都具有相同的“视图”(在 DataTemplate 中声明),但要绑定此视图,我想使用不同的视图模型(具体来说 - 相同的模型类 [ViewTabModel ] 但具有不同的数据)

选项卡的大小和数据一样在运行时声明,应该在 ViewTabModel 模型中。

在下面的示例中 - 我有两个标签,但更改它们不会更改标签(我一直都有:“Foo1”标签,即使我点击“Foo2”标签)

我使用 caliburn.micro 作为框架 - 使用 autofac 引导程序(如果重要的话) 我使用 propertyChanged.Fody (https://github.com/Fody/PropertyChanged) 来省略视图模型中的所有 propertychanged 内容。

我做错了什么?

=== 更新 ===

附加最小复制解决方案:

https://wetransfer.com/downloads/0b909bfd31a588dda99655f366eddad420170801192103/1d094a

请帮忙! :)

=== 更新 2 ===

我的问题还有什么不清楚的地方吗?:) 仍然没有 cmets,也没有赏金活动。

=== 更新 3 ===

我已经发布了 COMPLETE 视图页面 (xaml) 和 COMPLETE 模型代码(仅此而已)

我还发布了 AppBoostraper.cs 和 AppWindowManager.cs(但我想这里是无关紧要的)

AppBoostrapper.cs

using Autofac;
using TestWpfApp.ViewModels;

namespace TestWpfApp {
    using System;
    using System.Collections.Generic;
    using Caliburn.Micro;

    public class AppBootstrapper : CaliburnMetroAutofacBootstrapper<MainViewTestTabsViewModel>
    {
        protected override void ConfigureContainer(ContainerBuilder builder)
        {
            builder.RegisterType<AppWindowManager>().As<IWindowManager>().SingleInstance();
            var assembly = typeof(ShellViewModel).Assembly;
            builder.RegisterAssemblyTypes(assembly)
                .Where(item => item.Name.EndsWith("ViewModel") && item.IsAbstract == false)
                .AsSelf()
                .SingleInstance();
        }
    }
}

它正在继承 CaliburnMetroAutofacContainer (https://github.com/ziyasal/Caliburn.Metro)

AppWindowsManager.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Caliburn.Metro.Core;
using MahApps.Metro.Controls;

namespace TestWpfApp
{
    public class AppWindowManager : MetroWindowManager
    {
        public override MetroWindow CreateCustomWindow(object view, bool windowIsView)
        {
            if (windowIsView)
            {
                return view as ShellView;
            }

            return new ShellView
            {
                Content = view
            };
        }
    }
}

=== 更新 4 === 显然,从以下位置更改控制:

cal:Bind.Model="{Binding}" x:Name="DisplayName"

到:

Content="{Binding DisplayName}"

完成了工作。虽然我不太清楚为什么?

现在我想做同样的事情。只有这一次我希望我的观点受到约束。所以 ViewModel 是完全一样的。但这次:

MainViewTestTabsView

<UserControl  x:Class="TestWpfApp.Views.MainViewTestTabsView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:TestWpfApp.Views"
    xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
    xmlns:viewModels="clr-namespace:TestWpfApp.ViewModels"
    xmlns:cal="http://www.caliburnproject.org"
    mc:Ignorable="d" Width="500" Height="500">
<Grid>
    <TabControl Name="Items">
        <TabControl.ContentTemplate>
            <DataTemplate>
                <StackPanel>
                    <local:ViewTab cal:Bind.Model="{Binding}" />
                </StackPanel>
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>
</Grid>

ViewTab 视图是:

<UserControl  x:Class="TestWpfApp.Views.ViewTab"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:TestWpfApp.Views"
    xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
    xmlns:viewModels="clr-namespace:TestWpfApp.ViewModels"
    xmlns:cal="http://www.caliburnproject.org"
    mc:Ignorable="d" Width="300" Height="300">
<Grid>
    <StackPanel>
        <Label x:Name="DisplayName"></Label>
    </StackPanel>
</Grid>

=== 更新 5 => 决赛快乐 === 有人建议我应该坚持 ViewModel 第一个约定(正如我声明我正在使用的那样),我的尝试首先是 somhow 视图。所以我把它改成了:

<ContentControl cal:View.Model="{Binding ActiveItem}" />

但是没有渲染任何东西

如果我这样声明:

<ContentControl cal:View.Model="{Binding}" />

只有消息说:“找不到视图:[my_namspece].ViewTabModel 这很奇怪,让我思考。也许我不遵守约定。而且是真的……

我的模型被称为:

ViewTabModel

应该是这样的:

ViewTabViewModel

与视图完全相同。它应该被称为:

ViewTabView.xaml

之后,这样的构造:

<ContentControl cal:View.Model="{Binding}" />

工作正常!!感谢 arcticwhite 和 grek40 引导我找到这个解决方案

【问题讨论】:

  • 您是否缺少绑定?
  • 我很久以前就用过 Caliburn。您是否尝试过 ActivateItem(此处为 viewmodel)?
  • 在更改选项卡时,您需要使用 ActivateItem 激活视图
  • 也许你可以提议,在哪里以及如何放置这个“ActivateItem” - 这听起来并不明显:) 我会很感激 :)
  • caliburnmicro.codeplex.com/…。这里有例子

标签: c# wpf mvvm tabcontrol caliburn.micro


【解决方案1】:

好的... 我已经与Caliburn.Micro 合作过,所以我可以说我有一些经验,不是专业人士,但我设法让它发挥作用。

您的 MainViewTestTabsViewModel.cs:

 public interface IMainScreenTabItem : IScreen
    {
    }

    public class MainViewTestTabsViewModel : Conductor<IMainScreenTabItem>.Collection.OneActive
    {
        public MainViewTestTabsViewModel(IEnumerable<IMainScreenTabItem> tabs)
        {

            Items.Add(new ViewTabModel() {DisplayName = "Test"});
            Items.Add(new ViewTabModel() { DisplayName = "Test2" });
            Items.Add(new ViewTabModel() { DisplayName = "Test3" });
            Items.AddRange(tabs);
        }
    }

    public class ViewTabModel : Screen, IMainScreenTabItem
    {
        public ViewTabModel()
        {

        }
    }

还有你的 MainViewTestTabsView.xaml

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:TestWpfApp.ViewModels"
    xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
   xmlns:viewModels="clr-namespace:TestWpfApp.Views"
    xmlns:cal="http://www.caliburnproject.org"
    mc:Ignorable="d" Width="500" Height="500">
    <Grid>
        <TabControl x:Name="Items" >
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Label cal:Bind.ModelWithoutContext="{Binding}" x:Name="DisplayName" Height="200" Width="200"/>
                    </StackPanel>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </Grid>
    </UserControl>

附:为什么我在构造函数中删除了你的 displayName 变量...因为你不需要它,它已经在 Caliburn:Micro.Screen 作为属性。

编辑#2 该约定将起作用,只需在您的Label 中添加cal:Bind.ModelWithoutContext="{Binding}"(编辑答案)。

【讨论】:

  • 是的,它起作用了——但我不知道为什么。 caliburn.micro 不应该按照惯例绑定数据(x:Name 毕竟是 DisplayName)吗?它确实修复了最小的复制示例 - 但它仍然无助于我的真正问题,这有点复杂。我会更新我的问题。 (我需要将我的自定义视图模型与视图绑定)
  • 所以你说解决这个问题的正确方法是使用显式绑定 (Content="{Binding DisplayName}") 而不是依赖于 caliburn.micro 的约定?我知道这是可能的,但我认为它违背了最初的想法,特别是因为DisplayName 据说只是一个相当复杂的实际项目结构的最小示例。 €dit:Piotr 的评论比我快 :)
  • 唯一让我吃惊的是……不依赖约定 = 正常工作。我无法理解它;)再走一步,我就准备好了。我只需要更改这个简单的模板即可使用声明的视图(以及如何绑定它)更新 4 将在一分钟内完成
  • 更新 4 已准备就绪,正在等待意见。我试过 Content="{Binding}" 但没有成功
【解决方案2】:

现在我有时间来测试您的示例项目...正如我所评论的,您应该选择正确的绑定类型...

来自All About Actions,我猜周围会有其他文档来源,列出相同的基本信息:

  • Bind.Model - View-First - 将 Action.Target 和 DataContext 属性设置为指定实例。应用约定 到视图。字符串值用于从 国际奥委会容器。 (在 Window/UserControl/Page 等根节点上使用。)
  • Bind.ModelWithoutContext - View-First - 将 Action.Target 设置为指定实例。将约定应用于视图。 (采用 在 DataTemplate 内部。)
  • View.Model – ViewModel-First – 定位指定 VM 实例的视图并将其注入内容站点。设置虚拟机 到 Action.Target 和 DataContext。将约定应用于 查看。

如前所述,我不是 caliburn 专家,所以我必须尝试一下……第二个选项对我来说看起来最好(“在 DataTemplate 内部使用”),所以这里是工作结果:

来自

<Label  cal:Bind.Model="{Binding}" x:Name="DisplayName" Height="200" Width="200" />

替换为

<Label cal:Bind.ModelWithoutContext="{Binding}" x:Name="DisplayName" Height="200" Width="200" />

及其工作原理。

实际上,我建议在周围的堆栈面板中引入模型(数据模板根)

<StackPanel cal:Bind.ModelWithoutContext="{Binding}">
    <Label x:Name="DisplayName" Height="200" Width="200" />
</StackPanel>

【讨论】:

  • 我设法以另一种方式运行它 :) 通过使用: 一开始它不起作用(我尝试过这种方式- 甚至在我在 SOF 上发布问题之前。但在主要问题中(出于某种原因)更多的这个问题不起作用。我怎样才能在两个人之间分配赏金?因为你和 arctiwhite 帮助了我很多。
  • 你不能分割赏金。但是,您可以接受您认为最适合您的问题的答案,并赏金另一个答案,以纪念您的问题;)
  • 是的,我已经在 Stack meta 上找到了关于此主题的讨论。我不同意他们得出的结论。 arcticwhite 帮助我解决了问题的初始阶段。你帮助我引导我得出最终结论。这两个答案都不是完整的、复杂的和最终的。是的,失去 50 点声望点将是可耻的。对不起,伙计们 - 我必须掷骰子:) 无论如何谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-27
相关资源
最近更新 更多