繁体   English   中英

WPF 每个 TabItem 的初始焦点

[英]WPF Initial focus for each TabItem

好的,我知道这个标题看起来像是在 SO 周围都有答案,但是这里找到的答案都没有对我有用。 所以,这就开始了。

我有这个布局:

<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 TextBoxti1 TabItem被选中,并在dg DataGridti2 TabItem被选中。 另外,我真的很想在XAML设置它。

注意:我只能使用此处命名的控件,直到Page控件为止。

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

  • txt Control的父树中的所有父控件上设置FocusManager.FocusedElement="{Binding ElementName=txt}" (直到Page )。
  • txtdg控件上设置FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"
  • 通过TabControlSelectionChanged事件在代码中设置焦点:

    • if ( ti1.IsSelected ) { tc.UpdateLayout(); FocusManager.SetFocusedElement( sp, txt ); }
    • if ( ti1.IsSelected ) { tc.UpdateLayout(); txt.焦点(); }

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

<TextBox ... </TextBox>

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

正如我所说, XAML解决方案是需要的,但如果前者不可能,我也将解决一个代码。

好的, Keyur PATEL回答中的 Dispatcher 部分对我来说是解决方案,尽管不是完整的解决方案。 我的答案是使用Dispatcher更新TabControl布局,然后调用Focus Dispatcher 所以,对我来说,完整的答案是:

Dispatcher.BeginInvoke( (Action) (() => tc.UpdateLayout()) );
Dispatcher.BeginInvoke( (Action) (() => txt.Focus() ) );

或者您可以只使用Invoke来让 UI 线程等待您的Action

之所以必须使用Dispatcher ,是因为我首先用它来更改选定的选项卡。 至少,这是我最好的猜测。

您可以尝试类似于您的代码隐藏解决方案的方法,但具有以下变化:

<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,将焦点设置到文本字段

如何在 tabItem ın WPF 中集中控制(虽然对我来说它没有UpdateLayout()

使用扩展属性找到解决方案

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM