【问题标题】:Change tab of parent Window TabControl from child UserControl从子 UserControl 更改父窗口 TabControl 的选项卡
【发布时间】:2018-03-27 11:00:20
【问题描述】:

我有一个带有TabControl 的父窗口。每个选项卡都包含一个与之关联的UserControl。在我的UserControl 之一中,我有一个按钮。当我单击按钮时,我想更改父窗口中TabControl 的选定选项卡。

我正在使用 MVVM 模式,所以如果可能的话,我想在 XAML 中使用按钮上的 Command 属性来实现。

例如:

<Button Content="Switch Tab" Command="{Binding SwitchTabCommand}" />

提前感谢我的程序员伙伴!

父窗口视图模型:

public class CoolViewModel : BaseViewModel
{
    #region Properties

    public ObservableCollection<ITabViewModel> Tabs { get; set; }
    public ITabViewModel SelectedTab { get; set; }

    #endregion

    #region Constructor

    public CoolViewModel()
    {
        Tabs = new ObservableCollection<ITabViewModel>
        {
            new VeryNiceViewModel(),
            new VeryNiceViewModel()
        };
    }

    #endregion
}

这是选项卡内 UserControl 的代码:

public class VeryCoolViewModel : BaseViewModel, ITabViewModel
{
    #region Properties

    public ObservableCollection<Test> Tests { get; set; }
    public Test currentSelection { get; set; }
    public string TabHeader { get; set; }

    #endregion

    #region Commands

    ICommand GoToOtherTab { get; set; }

    #endregion

    #region Constructor

    public GabaritSelecteurViewModel()
    {
        Tests = new ObservableCollection<Test>
        {
            new Test { Title = "Title #1" },
            new Test { Title = "Title #2" },
            new Test { Title = "Title #3" },
            new Test { Title = "Title #4" },
            new Test { Title = "Title #5" }
        };

        TabHeader = "Tests";

        GoToOtherTab = new RelayCommand(GoToTab, parameter => true);
    }

    #endregion

    #region Methods

    private void GoToTab(object parameter)
    {
        // I don't know how to tell to the
        // parent window to go to the other tab...
    }

    #endregion
}

这是 UserControl 的 XAML(位于 TabControl 内):

<Button Content="Go to the other tab" Command="{Binding GoToOtherTab}" />

【问题讨论】:

    标签: c# wpf xaml mvvm user-controls


    【解决方案1】:

    您可以尝试添加到 VeryCoolViewModel(your UserControl VM) 事件中:

    public class VeryCoolViewModel : BaseViewModel, ITabViewModel
    {
        #region Properties
    
        public ObservableCollection<Test> Tests { get; set; }
        public Test currentSelection { get; set; }
        public string TabHeader { get; set; }
    
        public delegate void ChangeSelectedTab(string tabName)
        public event ChangeSelectedTab OnChangeSelectedTab
        #endregion
    
        #region Commands
    
        ICommand GoToOtherTab { get; set; }
    
        #endregion
    
        #region Constructor
    
        public GabaritSelecteurViewModel()
        {
            Tests = new ObservableCollection<Test>
            {
                new Test { Title = "Title #1" },
                new Test { Title = "Title #2" },
                new Test { Title = "Title #3" },
                new Test { Title = "Title #4" },
                new Test { Title = "Title #5" }
            };
    
            TabHeader = "Tests";
    
            GoToOtherTab = new RelayCommand(GoToTab, parameter => true);
        }
    
        private void GoToTab(object parameter)
        {
                OnChangeSelectedTab?.Invoke((string)parameter);
        }
    }
    

    在构造函数中进入父窗口虚拟机:

    public CoolViewModel()
    {
        Tabs = new ObservableCollection<ITabViewModel>
        {
             new VeryNiceViewModel(),
             new VeryNiceViewModel()
        };
        Tabs.ForEach(x =>{
            x.OnChangeSelectedTab += x_OnChangeSelectedTab
        });
    
    }
    
    private void x_OnChangeSelectedTab(string tabName)
    {
         // select from List of tabItems tabItem with name == tabName and then set propetry in this tabItem to true.
         SomePropertyInParentViewModel = true;
    }
    

    在视图中:

    <TabItem x:Name="TabWhatYouNeed" IsSelected="{Binding SomePropertyInParentViewModel}">
    

    【讨论】:

      【解决方案2】:

      你可以做一些有点“hacky”但非常简单的事情。如果您的每个 UserControls 都没有自己的 ViewModel(不太清楚为什么需要它),那就不会那么麻烦了。

      无论如何,我们的目标是到达CoolViewModel。我们怎么去那里? RelativeSource Binding。简而言之,它使您能够在不同的范围内进行绑定(除了您自己的DataContext,在此示例中为 UserControl)。

      所以,我们知道您有一个 TabControl 来保存所有这些 UserControl,我们知道这个 TabControl 的 DataContext 是 CoolViewModel。

      1. 将Command 放入CoolViewModel,如下所示:

        public ICommand SwitchTabCommand {get;set;}

      2. 使用 UserControl 绑定到它:

        &lt;Button Content="Go to the other tab" Command= "{Binding RelativeSource={RelativeSource AncestorType={x:Type TabControl}}, Path=DataContext.SwitchTabCommand}" /&gt;

      所以基本上你正在寻找最近的祖先TabControl,通过它的DataContext寻找命令SwitchTabCommand

      【讨论】:

      • 如果有人可以向我解释如何创建格式良好的代码块,那就太好了。
      • 有效!非常感谢! XAML 设计器向Path=DataContext.SwitchToCommand 抱怨,所以我不得不将其更改为:`Path=DataContext.(viewModels:CoolViewModel.SwitchToCommand),否则它会告诉我:无法在数据上下文中解析属性“SwitchToCommand”输入对象.
      • 是的,我在回答中这样做了...但它不会为 xaml 和 c# 着色
      • 奇怪...只是运行时问题还是编译问题?
      • 在编译和运行之前。它在 XAML 代码中带有蓝色下划线。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-23
      • 1970-01-01
      • 2010-11-20
      • 1970-01-01
      • 2012-01-10
      • 2014-03-23
      相关资源
      最近更新 更多