如何知道动态创建的 TabItem 的索引
Posted
技术标签:
【中文标题】如何知道动态创建的 TabItem 的索引【英文标题】:How to know the index of dynamically created 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
。
【参考方案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),但这超出了本主题的范围。
【讨论】:
以上是关于如何知道动态创建的 TabItem 的索引的主要内容,如果未能解决你的问题,请参考以下文章