【发布时间】: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” - 这听起来并不明显:) 我会很感激 :)
标签: c# wpf mvvm tabcontrol caliburn.micro