【问题标题】:How to know the index of dynamically created TabItem如何知道动态创建的 TabItem 的索引
【发布时间】:2014-10-29 07:36:49
【问题描述】:

我在 xaml 中有这样的:

<controls:TabControl Grid.Row="0" BorderThickness="0" Background="White" 
                         ItemsSource="{Binding TabList, Mode=TwoWay, Converter={StaticResource TabConverter}}"                        
                         SelectedItem="{Binding CurrentItem, Mode=TwoWay}"/>

在视图模型中我有:

 private TabItem currentItem;
    public TabItem CurrentItem
    {
        get { return currentItem; }
        set 
        {
            //currentItem.Content               
            currentItem = value;
          int index = currentItem.TabIndex;  //IT GIVES STRANgE INDEX ON DEBUGGING ob Tab click (like 22255788586)                   
            OnPropertyChanged("CurrentItem");
        }
    }

但是这个 TabList(在 xaml 中)是这样动态生成的:

public void AddVersion(ProgramVersion pv) //it creates the TabList
        {
            if (pv != null)
            {               
                if (index == -1)
                {                      
                    TabList.Add(new ProgramVersionItemViewModel(pv));                    
                    OnPropertyChanged("TabList");                
                }                
            }
        }

每次按下按钮我都会调用函数 AddVersion(version);它会添加到 TabList 中。

问题是当我单击 CurrentItem(动态创建的 TabItems (TabList) 数量)时,它会给出非常大的奇怪地址(如 222557456)。

我获取当前项目索引的方法是错误的吗? (int index = currentItem.TabIndex;) ?

【问题讨论】:

  • TabIndex 不是选项卡的索引 - 它用于在按 TAB 键在控件之间循环时对控件进行排序。
  • TabIndex 并不意味着 TabControl 内的项目索引。由于您有一个 ViewModel 列表,SelectedItem 可能不会返回 TabItem,它应该是指绑定到当前TabItem的ViewModel。所以你可以试试这个TabList.IndexOf(CurrentItem)
  • @Luaan 那么如何在这里解决该解决方案以了解在 CurrentItem 集合内单击的当前项目的索引?
  • @Claw 执行 siad 给出的操作:错误参数 1:无法从 'System.Windows.Controls.TabItem' 转换为 'ViewModel.ProgramVersionItemViewModel'
  • 您只需将Tag 属性设置为pv,然后当您想阅读它时,只需进行显式转换-(ProgramVersion)currentItem.Tag

标签: c# .net xaml tabcontrol tabitem


【解决方案1】:

说实话,这是一种方法。这里可能是一个更好的解决方案:

    private void Button1_Click(object sender, RoutedEventArgs e)
    {
        TabControl1.Items.Add(new TabItem() { TabIndex = 0, Header = "Tab 0" });
        TabControl1.Items.Add(new TabItem() { TabIndex = 1, Header = "Tab 1" });
        TabControl1.Items.Add(new TabItem() { TabIndex = 2, Header = "Tab 2" });
        TabControl1.Items.Add(new TabItem() { TabIndex = 3, Header = "Tab 3" });
    }

请注意,我们正在添加 new TabItem() 并为其提供标签索引和标题。使用这种方法更加动态和可靠。

因此,在您的示例中,您可能会执行以下操作:

        if (pv != null)
        {
            if (index == -1)
            {
                TabList.Add(new TabItem() { TabIndex = <EnumeratedValue>, Header = "Tab " + <EnumeratedValue>.ToString()});
            }
        }

【讨论】:

  • 如果您使用的是 MVVM 方法,由于它们绑定 CurrentItem 的方式,OP 可能会使用这种方法,这不是一个更好的解决方案。此外,TabIndex 不是选项卡的索引(正如其他评论者已经指定的那样),而是用户通过它们进行选项卡时使用的控件的顺序。选项卡上没有可用的索引,父容器具有所选项目的索引 (SelectedIndex) iirc。
  • 正确,其他人也发表了同样的评论。虽然如果您是动态添加和删除选项卡,为什么不使用 tabindex 呢?如果最终用户希望通过选项卡进行 TAB,您的订单将始终得到明确定义。
  • 因为 WPF/SL 会根据控件在页面上的位置自动设置标签索引。除非您遇到严重问题或者您想将其设置为不直观的顺序,否则您不需要明确设置它
  • Charleh - 一开始我不相信你,然后我试了一下。我的立场是正确的。
【解决方案2】:

7 年后仍然没有令人满意的答案..

这是一个快速的虚拟修复,只要您使用 TabItem 实例来填充父 TabControl 并且不要弄乱复杂的转换器。

将下面的代码放在实用程序静态(内部)类中。添加适当的引用,如using System.Windows.Controls(或者直接在System.Windows.Controls命名空间下创建静态类)

/// <summary>
/// Gets the current index of the Tab under a TabControl.
/// </summary>
/// <param name="tabItem">This TabItem.</param>
/// <param name="defaultReturn">A default value to return if no index could be retrieved.</param>
/// <returns>The sequential index of the tab.</returns>
public static Int32 GetIndex(this TabItem tabItem, Int32 defaultReturn = 0) 
{
    if (tabItem == null) 
        throw new ArgumentNullException("tabItem", "TabItem is null.");
    if (tabItem.Parent is TabControl) 
    {
        TabControl parent = (TabControl)tabItem.Parent;
        int i = 0;

        foreach (var tab in parent.Items) 
        {
            if (ReferenceEquals(tab, tabItem)) 
                return i;

            i = i + 1;
        }
    }

    return defaultReturn;
}

那么你就可以使用它了:

// Select the latest created tab...
Dispatcher.BeginInvoke((Action)(() => TheTabControl.SelectedIndex = CurrentItem.GetIndex(0)));

您可以在相同的基础上创建其他扩展方法,例如 TabControl.GetLastTab() 或 TabItem.SetIndex(0),但这超出了本主题的范围。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-28
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-09
    • 1970-01-01
    • 2021-11-05
    相关资源
    最近更新 更多