我是WPF&MVVM&Caliburn的新手,所以我请你放纵:)
我在使用动态创建的模型绑定TabControl时遇到问题。 Tabcontrol正在正确创建,但更改选项卡不会切换用于绑定" view"的视图模型。 (我使用viewmodel第一种方法)
我已根据这个问题制定了解决方案: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具有多个选项卡。每个标签都有相同的&#34;视图&#34; (在DataTemplate中声明)但是要绑定此视图我想使用不同的viewModel(具体 - 相同的模型类[ViewTabModel]但具有不同的数据)
选项卡的大小将在运行时以及数据中声明,这些数据应该在ViewTabModel模型中。
在下面的示例中 - 我有两个选项卡,但更改它们不会更改标签(我有所有时间:&#34; Foo1&#34;标签,即使我点击&#34; Foo2&#34;标签)
我使用caliburn.micro作为框架 - 使用autofac bootstrap(如果重要的话) 我使用propertyChanged.Fody(https://github.com/Fody/PropertyChanged)来省略viewmodels中的所有propertychanged东西。
我做错了什么?
=== UPDATE ===
附加最小的复制解决方案:
https://wetransfer.com/downloads/0b909bfd31a588dda99655f366eddad420170801192103/1d094a
请尽快帮忙! :)
===更新2 ===
关于我的问题有什么不清楚的地方吗?:)仍然没有评论,没有关于它的赏金事件。
===更新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 =&#34; {结合}&#34; X:名称=&#34; DisplayName的&#34;
为:
内容=&#34; {Binding DisplayName}&#34;
做了什么工作。虽然我不太清楚为什么?
现在我想做同样的事情。只有这次我希望我的视图被绑定。所以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 =&gt;快乐的决赛=== 我已经被吸食了,我应该坚持使用ViewModel的第一个约定(因为我宣称我正在使用),我的尝试首先是somhow视图。所以我把它改成了:
<ContentControl cal:View.Model="{Binding ActiveItem}" />
但是没有任何东西呈现
如果我这样声明:
<ContentControl cal:View.Model="{Binding}" />
只有消息说:&#34;找不到以下视图:[my_namspece] .ViewTabModel 这很奇怪,让我思考。也许我不坚持这个惯例。这是真的......
我的模型被称为:
ViewTabModel
它应该是:
ViewTabViewModel
与视图完全相同。它应该被称为:
ViewTabView.xaml
之后,这样的结构:
<ContentControl cal:View.Model="{Binding}" />
工作正常!!感谢arcticwhite和grek40带领我找到这个解决方案
答案 0 :(得分:3)
Okay...
I have already worked with Caliburn.Micro
, so I can say I have some experience, not a pro, but I manage to make it working.
Your 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()
{
}
}
And your 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>
P.S. Why I removed your displayName variable in constructor... Because you don't need it, it's already in the Caliburn:Micro.Screen
as a property.
Edit #2
The convention will work, just add cal:Bind.ModelWithoutContext="{Binding}"
inside your Label
(Edited the answer).
答案 1 :(得分:1)
现在我有时间测试您的示例项目......正如我评论的那样,您应该选择正确的绑定类型......
从All About Actions开始,我猜会有其他文档来源,列出相同的基本信息:
- Bind.Model - View-First - 将Action.Target和DataContext属性设置为指定的实例。适用约定 到了视野。字符串值用于解析来自的实例 IoC容器。 (在Window / UserControl / Page等根节点上使用。)
- Bind.ModelWithoutContext - View-First - 将Action.Target设置为指定的实例。将约定应用于视图。 (使用 在DataTemplate中。)
- View.Model - ViewModel-First - 找到指定VM实例的视图,并将其注入内容站点。设置VM 到Action.Target和DataContext。适用于的约定 图。
如上所述,我不是校准专家,所以我不得不尝试...第二个选项对我来说最好(“在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" />
及其工作。
实际上,我建议在周围的堆栈面板中引入模型(datatemplate root)
<StackPanel cal:Bind.ModelWithoutContext="{Binding}">
<Label x:Name="DisplayName" Height="200" Width="200" />
</StackPanel>