我正在构建一个LOB应用程序,其中包含一个主要部分和一个带有各种TabItem的TabControl。在点击保存时,想法是突出显示任何错误字段,错误的第一个字段获得焦点。
如果错误的第一个也是唯一的字段位于“未选定”选项卡上,则该选项卡应该被选中,错误的字段应该突出显示并具有焦点。但是我无法让它发挥作用。
似乎正在发生的事情是Unselected选项卡不在可视化树中,因此您无法导航回拥有的TabItem并使其成为TabControl中当前选定的TabItem。
有没有人知道如何实现这一目标?
答案 0 :(得分:4)
加载TabItem:
tabControl.SelectedItem = tabItemOfInterest;
tabControl.UpdateLayout();
这会导致tabItemOfInterest与TabItem中包含的所有控件一起加载。
以下单行不会加载tabItemOfInterest:
tabControl.SelectedItem = tabItemOfInterest;
但是,我会对大卫采用的方法非常感兴趣,以达到错误的控制。
答案 1 :(得分:1)
我是如何解决的(通过询问首席架构师)......
使用一种方法Activate创建一个接口ITabActivator。
创建一个派生自Grid和ITabActivator的类,名为TabPageActivator。其构造函数采用TabITem和TabControl。
不是向TabItem.Contents添加简单的Grid,而是添加TabPageActivator。
将父检测更改为使用...
DependencyObject parent = _Control.Parent;
...而不是使用VisualTreeHelper。
因此,当您导航层次结构测试...
时if(parent是TabActivator) (父级为ITabActivator).Activate()
...所以当调用Activate时
m_TabControl.SelectedItem = m_TabItem; //来自构造函数参数。
...不要忘记你可能有嵌套标签,所以你需要继续上层。
答案 2 :(得分:1)
我使用TabControls在我的某个网站(YinYangMoney)上进行导航,并构建了一些扩展方法,帮助我使用标记名称选择标签。以下是适合您的片段。
扩展程序类:
using System;
using System.Linq;
using System.Windows.Controls;
namespace MyApplication
{
internal static class Extensions
{
// Extension for TabControl
internal static void SelectTab(this TabControl tabControl, this TabItem tabItem)
{
if (tabControl == null || tabItem == null)
return null;
SelectTab(tabControl, tabItem.Tag);
}
// Extension for TabControl
internal static void SelectTab(this TabControl tabControl, string tabTagName)
{
if (tabControl == null)
return null;
// Find the TabItem by its Tag name
TabItem mainTabItem = tabControl.FindByTag(tabTagName);
if (mainTabItem == null)
return;
// Check to see if the tab needs to be selected
if (tabControl.SelectedItem != mainTabItem)
tabControl.SelectedItem = mainTabItem;
}
// Extension for TabControl
internal static TabItem FindByTag(this TabControl tabControl, string tagFragment)
{
if (tabControl == null || tagFragment == null)
return null;
return tabControl.Items
.OfType<TabItem>()
.Where(item => item.Tag != null && item.Tag.ToString().StartsWithIgnoreCase(tagFragment))
.FirstOrDefault();
}
// Extension for string
internal static bool StartsWithIgnoreCase(this string source, string target)
{
return source.StartsWith(target, StringComparison.CurrentCultureIgnoreCase);
}
}
}
TabControl和TabItems的XAML看起来像这样:
<Controls:TabControl x:Name="x_TabControl">
<Controls:TabItem Header="Welcome" Tag="/Home/Welcome" x:Name="x_WelcomeTab" />
<Controls:TabItem Header="FAQ" Tag="/Home/FAQ" />
<Controls:TabItem Header="Contact Us" Tag="/Home/Contact_Us" />
<Controls:TabItem Header="Privacy Policy" Tag="/Home/Privacy_Policy" />
<Controls:TabItem Header="My Account" Tag="/Home/My_Account" />
</Controls:TabControl>
您可以选择欢迎TabItem,如下所示:
x_TabControl.SelectTab("/Home/Welcome");
或
x_TabControl.SelectTab(x_WelcomeTab);
答案 3 :(得分:1)
我的解决方案使用附加属性TabItem。 创建课程 TabItemExtender :
/// <summary>
/// TabItem Extender class with TabItem property
/// </summary>
public class TabItemExtender
{
#region property getters/setters
/// <summary>
/// TabItem attached dependency property
/// </summary>
public static readonly DependencyProperty TabItemProperty = DependencyProperty.RegisterAttached("TabItem", typeof(TabItem), typeof(TabItemExtender), null);
/// <summary>
/// TabItem Property getter
/// </summary>
public static TabItem GetNavigateUri(DependencyObject source)
{
return (TabItem)source.GetValue(TabItemExtender.TabItemProperty);
}
/// <summary>
/// TabItem Property setter
/// </summary>
public static void SetNavigateUri(DependencyObject target, TabItem value)
{
target.SetValue(TabItemExtender.TabItemProperty, value);
}
#endregion
}
接下来在 TabControl 加载事件:
上执行此操作private void ExtendedTabControl_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
foreach (object item in this.Items)
{
var tabItem = item as TabItem;
if (tabItem != null && tabItem.Content != null)
{
var element = (FrameworkElement)tabItem.Content;
element.SetValue(TabItemExtender.TabItemProperty, tabItem);
}
}
}
,然后设置焦点:
var element = (UIElement)control;
while (element != null)
{
//Get TabItem
var tabItem = (TabItem)element.GetValue(TabItemExtender.TabItemProperty);
if (tabItem != null)
{
if (!tabItem.IsSelected && tabItem.IsEnabled)
{
tabItem.IsSelected = true;
((TabControl)tabItem.Parent).UpdateLayout();
}
break;
}
element = (UIElement)VisualTreeHelper.GetParent(element);
}
control.Focus();
答案 4 :(得分:0)
我知道一种方式,但它很难看。它涉及使用间隔为几毫秒的DispatcherTimer。在Page_Loaded中,您将启动计时器。然后在每个刻度线上为其中一个标签项设置IsSelected = true。在下一个勾选中,它选择下一个选项卡项等,直到选中所有选项卡。然后你必须再次选择第一个项目并终止计时器。这将强制加载选项卡项中的视觉效果。
在此操作过程中,您还必须使用边框或其他内容覆盖TabControl。否则,用户将快速浏览所有标签项。