好的,我知道这个标题看起来好像都有答案,但这里找到的答案都不适用于我。所以,到此为止。
我有这个布局:
<Window>
<Grid>
<DockPanel>
<TabControl>
<TabItem>
<Page x:Name="p">
<Grid x:Name="g2">
<TabControl x:Name="tc">
<TabItem x:Name="ti1">
<StackPanel x:Name="sp">
<C:TextBox x:Name="txt"/>
</StackPanel>
</TabItem>
<TabItem x:Name="ti2">
<C:DataGrid x:Name="dg"/>
</TabItem>
</TabControl>
</Grid>
</Page>
</TabItem>
</TabControl>
</DockPanel>
</Grid>
</Window>
现在,我的目标是在txt
TextBox
被选中时关注ti1
TabItem
,dg
DataGrid
时关注ti2
TabItem
1}} XAML
被选中。另外,我真的很想在Page
中设置它。
注意:我只能使用此处命名的控件,所以直到FocusManager.FocusedElement="{Binding ElementName=txt}"
控制。
到目前为止我尝试了什么:
txt
Control
的父树中的所有父控件上设置Page
(直至FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"
)。txt
和dg
控件上设置TabControl
。通过SelectionChanged
的{{1}}事件:
TextBox
和DataGrid
控件的创建方式与UserControl
类似,但实际上是继承TextBox
和DataGrid
的类,如下所示:
<TextBox ... </TextBox>
和
public partial class TextBox : System.Windows.Controls.TextBox
正如我所说的那样,XAML
解决方案是理想的,但如果不可能,我也会选择代码一。
答案 0 :(得分:1)
你可以尝试类似于你的代码隐藏解决方案,但有这种变化:
<TabControl x:Name="tc" SelectionChanged="tc_selectionChanged">
并在代码背后:
InitializeComponent();
//if you know which control to focus by default when page is first loaded
Dispatcher.BeginInvoke(new Action(() => { txt.Focus(); }));
和
private void tc_selectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ti1.IsSelected)
{
txt.Focus();
}
else if (ti2.IsSelected)
{
dg.Focus();
}
}
我在自己的WPF应用程序上尝试了这个确切的设置,所以我知道它有效。
有用的链接:
WPF TabControl On SelectionChanged, set focus to a text field
和
How to focus control in the tabItem ın WPF(虽然对我而言没有UpdateLayout()
)
答案 1 :(得分:0)
好的,来自 Keyur PATEL&#39; 答案的Dispatcher部分是我的解决方案,虽然不是完整的解决方案。我的答案是使用TabControl
更新Dispatcher
布局,然后调用Focus
Dispatcher
。所以,对我来说完整的答案是:
Dispatcher.BeginInvoke( (Action) (() => tc.UpdateLayout()) );
Dispatcher.BeginInvoke( (Action) (() => txt.Focus() ) );
或者您只能使用Invoke
代替UI线程等待Action
。
由于我必须使用Dispatcher
的原因,这是因为我首先使用它来更改选定的选项卡。这是我最好的猜测,至少。
答案 2 :(得分:0)
使用扩展属性找到解决方案
public static class TabItemExtention
{
public static bool GetIsSelected(DependencyObject obj)
{
return (bool)obj.GetValue(IsSelectedProperty);
}
public static void SetIsSelected(DependencyObject obj, bool value)
{
obj.SetValue(IsSelectedProperty, value);
}
public static readonly DependencyProperty IsSelectedProperty =
DependencyProperty.RegisterAttached(
"IsSelected", typeof(bool), typeof(TabItemExtention),
new UIPropertyMetadata(false, OnIsSelectedPropertyChanged));
private static void OnIsSelectedPropertyChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var uie = (UIElement)d;
var tabItem = uie as TabItem;
if (tabItem != null)
tabItem.IsSelected = (bool)e.NewValue;
if ((bool)e.NewValue)
{
uie.UpdateLayout();
}
}
}
XAML:
ctrl:TabItemExtention.IsSelected="{Binding IsTabNewCustomsDelaySelected}"