C# WPF+Caliburn Micro+MVVM:TabItem处理

C# WPF+Caliburn Micro+MVVM:TabItem处理,c#,wpf,mvvm,tabitem,C#,Wpf,Mvvm,Tabitem,我试图创建一个弹出窗口,其中包含使用WPF、Caliburn Micro和MVVM模式的tabcontrol,在这种情况下不需要使用代码隐藏。tabcontrol包含多个tabitem。在挖掘了一些线程之后,我结合了找到的解决方案,可以创建弹出窗口,并用tabcontrol及其tabitems填充它 问题:选项卡项显示视图模型中的内容文本,但不显示视图中的内容。请看一下附在这里的代码 我希望看到文本选项卡项1作为TabItem1标题,文本选择项1作为TabItem1中的内容。现在TabItems

我试图创建一个弹出窗口,其中包含使用WPF、Caliburn Micro和MVVM模式的tabcontrol,在这种情况下不需要使用代码隐藏。tabcontrol包含多个tabitem。在挖掘了一些线程之后,我结合了找到的解决方案,可以创建弹出窗口,并用tabcontrol及其tabitems填充它

问题:选项卡项显示视图模型中的内容文本,但不显示视图中的内容。请看一下附在这里的代码

我希望看到文本选项卡项1作为TabItem1标题,文本选择项1作为TabItem1中的内容。现在TabItems的标题和内容都包含相同的文本tabitem1

我错过什么了吗?我在此附上代码。请随意更改代码。如有任何提示,我们将不胜感激

代码顺序:

TabItem1、TabItem2视图和viewmodel 伊塔比坦 弹出窗口视图和视图模型 AppBootstrapper、Shell视图和viewmodel TabItem1ViewModel TabItem2ViewModel具有相同的内容

public class TabItem1ViewModel : Screen, ITabItem
{
    public TabItem1ViewModel() => DisplayName = "Tab Item 1";
}
<UserControl
    x:Class="CmTabControl.Views.TabItem1View"
    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"
    d:DesignHeight="450"
    d:DesignWidth="800"
    mc:Ignorable="d">
    <Grid>
        <TabItem x:Name="TabItem1" Header="{Binding Path=DisplayName}">
            <Grid x:Name="TabItem1ContentGrid">
                <Label HorizontalAlignment="Left"                     
                    VerticalAlignment="Top"
                    Content="Selection One" />
            </Grid>
        </TabItem>
    </Grid>
</UserControl>
注意:在下面的TabItem视图中,我使用Label显示文本选择项,但该文本根本不显示。只有在视图模型中定义的“显示名称”选项卡项1显示为选项卡项1的内容

TabItem1View TabItem2View具有相同的内容

public class TabItem1ViewModel : Screen, ITabItem
{
    public TabItem1ViewModel() => DisplayName = "Tab Item 1";
}
<UserControl
    x:Class="CmTabControl.Views.TabItem1View"
    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"
    d:DesignHeight="450"
    d:DesignWidth="800"
    mc:Ignorable="d">
    <Grid>
        <TabItem x:Name="TabItem1" Header="{Binding Path=DisplayName}">
            <Grid x:Name="TabItem1ContentGrid">
                <Label HorizontalAlignment="Left"                     
                    VerticalAlignment="Top"
                    Content="Selection One" />
            </Grid>
        </TabItem>
    </Grid>
</UserControl>
PopUpViewModel

弹出视图

应用引导程序

ShellViewModel

ShellView

添加:实时可视化树的屏幕截图。
我找到了一个使用模板的解决方案:

PopUpViewModel添加选定选项卡:

现在,您只需将TabItem内容添加到页面中,TabItem1View:

编辑:


SelectedTab就在那里,因此默认情况下第一个选项卡处于选中状态。

如果在Visual Studio中运行Snoop或Live Visual tree调试工具,那么是否将Grid/Label视为TabItem的子级?否,我只将TextBlock视为TabItem的子级,没有标签。我在上面的问题上添加了截图。你希望看到什么?你的PopupViewModel在哪里?哦,对不起。我刚刚添加了PopUpViewModel及其视图。我希望在TabItem1中看到TabItem1作为TabItem1标题,而文本选择作为内容。现在TabItems的标题和内容都包含相同的文本Tab Item 1。将列表绑定到TabControl是否重要?回答得很好。你得到赏金了!:谢谢,很高兴我能帮忙。
<Window
    x:Class="CmTabControl.Views.PopUpView"
    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:local="clr-namespace:CmTabControl.Views"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="PopUpView"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <Grid Margin="3,8,3,3" HorizontalAlignment="Stretch"
        VerticalAlignment="Stretch">
        <TabControl x:Name="TabItems" />
    </Grid>
</Window>
public class AppBootstrapper : BootstrapperBase
{
    private readonly SimpleContainer _container = new SimpleContainer();

    public AppBootstrapper() => Initialize();
    protected override object GetInstance(Type serviceType, string key) => _container.GetInstance(serviceType, key);
    protected override IEnumerable<object> GetAllInstances(Type serviceType) => _container.GetAllInstances(serviceType);
    protected override void BuildUp(object instance) => _container.BuildUp(instance);

    protected override void Configure()
    {
        base.Configure();

        _container.Singleton<IWindowManager, WindowManager>();
        _container.Singleton<IEventAggregator, EventAggregator>();
        _container.Singleton<ShellViewModel>();
        _container.PerRequest<PopUpViewModel>(); // Or Singleton if there'll only ever be one
    }

    protected override void OnStartup(object sender, StartupEventArgs e)
    {
        base.OnStartup(sender, e);
        DisplayRootViewFor<ShellViewModel>();
    }
}
public class ShellViewModel : Conductor<object>.Collection.AllActive
{
    private IWindowManager _windowManager;

    public ShellViewModel(PopUpViewModel popUpVm)
    {
        DisplayName = "Shell Window";
        PopUpViewModel = popUpVm;
    }

    public PopUpViewModel PopUpViewModel { get; set; }

    public sealed override void ActivateItem(object item) => base.ActivateItem(item);

    public void OpenPopUp()
    {
        ActivateItem(PopUpViewModel);
        if (_windowManager == null) _windowManager = new WindowManager();
        _windowManager.ShowDialog(PopUpViewModel, null, null);
    }

    public sealed override string DisplayName { get; set; }
}
<UserControl
    x:Class="CmTabControl.Views.ShellView"
    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"
    d:DesignHeight="300"
    d:DesignWidth="300"
    mc:Ignorable="d">
    <Grid Width="300" Height="300"
        HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button x:Name="OpenPopUp" Width="100" Height="35"
            Content="Open Popup" />
    </Grid>
</UserControl>
public sealed class PopUpViewModel : Screen
{
    private readonly BindableCollection<ITabItem> _tabItems = new BindableCollection<ITabItem>();
    private IScreen _selectedTab;


    public PopUpViewModel()
    {
        DisplayName = "Popup";
        TabItems.Add(new TabItem1ViewModel());
        TabItems.Add(new TabItem2ViewModel());
        SelectedTab = TabItems.FirstOrDefault();
    }


    public BindableCollection<ITabItem> TabItems
    {
        get => _tabItems;
        set
        {
            if(_tabItems == null)
                return;
            _tabItems.Clear();
            _tabItems.AddRange(value);
            NotifyOfPropertyChange(() => TabItems);
        }
    }

    public IScreen SelectedTab
    {
        get => _selectedTab;
        set
        {
            _selectedTab = value;
            NotifyOfPropertyChange();
        }
    }
}
<Grid Margin="3, 8, 3, 3"
      HorizontalAlignment="Stretch"
      VerticalAlignment="Stretch">
    <TabControl ItemsSource="{Binding TabItems}"
                SelectedItem="{Binding SelectedTab,
                               UpdateSourceTrigger=PropertyChanged}">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <Label Content="{Binding DisplayName}" />
            </DataTemplate>
        </TabControl.ItemTemplate>
        <TabControl.ContentTemplate>
            <DataTemplate>
                <ContentControl cal:View.Model="{Binding}" />
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>
</Grid>
<UserControl x:Class="WpfTestApp.Views.Tabs.TabItem1View"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:WpfTestApp.Views.Tabs"
             mc:Ignorable="d"
             d:DesignHeight="450"
             d:DesignWidth="800">

    <Grid x:Name="TabItem1ContentGrid">
        <Label HorizontalAlignment="Left"
               VerticalAlignment="Top"
               Content="Selection One" />
    </Grid>
</UserControl>