WPF每个TabItem的初始焦点

时间:2017-10-09 07:59:49

标签: c# wpf xaml

好的,我知道这个标题看起来好像都有答案,但这里找到的答案都不适用于我。所以,到此为止。

我有这个布局:

<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 TabItemdg DataGrid时关注ti2 TabItem 1}} XAML被选中。另外,我真的很想在Page中设置它。

注意:我只能使用此处命名的控件,所以直到FocusManager.FocusedElement="{Binding ElementName=txt}"控制。

到目前为止我尝试了什么:

  • txt Control的父树中的所有父控件上设置Page(直至FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}")。
  • txtdg控件上设置TabControl
  • 通过SelectionChanged的{​​{1}}事件:

    在代码中设置焦点
    • if(ti1.IsSelected) { tc.UpdateLayout(); FocusManager.SetFocusedElement(sp,txt); }
    • if(ti1.IsSelected) { tc.UpdateLayout(); txt.Focus(); }

TextBoxDataGrid控件的创建方式与UserControl类似,但实际上是继承TextBoxDataGrid的类,如下所示:

<TextBox ... </TextBox>

public partial class TextBox : System.Windows.Controls.TextBox

正如我所说的那样,XAML解决方案是理想的,但如果不可能,我也会选择代码一。

3 个答案:

答案 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}"