2016-10-09 62 views
1

私はWPFとフォーカスについていくつかの他の投稿を行っており、私のコードでは見当たりません。私は、厳密なMVVMを使用しているアプリケーションで作業しているので、コードビハインドが必要なときに添付のビヘイビアを使用してビューファイル内のコードビハインドを回避しようとしていますが、この時点では、ビューの後ろでは機能しません。WPFフォーカスは、論理フォーカスとキーボードフォーカスの両方を取得できません。

メインウィンドウのあるアプリケーションがあり、ホットキーで検索ウィンドウのポップアップを作成しようとしています。ユーザーがホットキーを押すとすぐに、キーボードのフォーカスが検索テキストになるようにして、ちょうどホットキーにして検索語を入力したいと思います。キーボードが要素に焦点を当てていると主張しているにもかかわらず、論理的な焦点を除いてすべてがこの時点で機能しています。

コードからキーボードと論理フォーカスの両方を同時に取得できないようです。ただし、検索ボックスが表示されるとすぐにTabキーを押すと、テキストボックスに直接挿入されます。

メインウィンドウコード:

<ribbon:RibbonWindow x:Class="MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary" 
    xmlns:attached="clr-namespace:UserInterface.Attached" 
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
    xmlns:command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF45" 
    xmlns:viewModels="clr-namespace:UserInterface.ViewModels" 
    xmlns:views="clr-namespace:UserInterface.Views" 
    xmlns:layout="clr-namespace:UserInterface.ViewModels.Layout" 
    xmlns:layout1="clr-namespace:UserInterface.Views.Layout" 
    MinHeight="560" 
    MinWidth="950" 
    WindowStartupLocation="CenterScreen" 
    Icon="{Binding Layout.IconPath}" 
    DataContext="{Binding Main, Source={StaticResource Locator}}" 
    FocusManager.FocusedElement="{Binding ElementName=LayoutControl}" 
    Title="{Binding Layout.Title}"> 

<!-- Ribbon menu shortcuts --> 
<Window.InputBindings> 
    <KeyBinding Modifiers="Control" Key="T" Command="{Binding Layout.Commands[GlobalObjectSearch]}" /> 
</Window.InputBindings> 

<Grid> 
    <ContentPresenter Content="{Binding Layout}" x:Name="LayoutControl"> 
     <ContentPresenter.Resources> 
      <DataTemplate DataType="{x:Type layout:MainViewModel}"> 
       <layout1:MainView/> 
      </DataTemplate> 
     </ContentPresenter.Resources> 
    </ContentPresenter> 
</Grid> 
</ribbon:RibbonWindow> 

コードは、検索ウィンドウを作るためには、表示されます。

public SelfClosingDialogView ShowSelfClosingDialog(IWindowDialogViewModel dataContext) 
    { 
     dataContext.CheckWhetherArgumentIsNull(nameof(dataContext)); 

     var view = new SelfClosingDialogView 
     { 
      DataContext = dataContext, 
      Owner = Application.Current?.MainWindow 
     }; 

     view.Show(); 

     return view; 
    } 

検索ウィンドウコード(再利用するので、ジェネリック):私の検索のための

<Window x:Class="UserInterface.Views.DialogViews.SelfClosingDialogView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:attached="clr-namespace:UserInterface.Attached" 
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
    mc:Ignorable="d" 
    SizeToContent="WidthAndHeight" 
    WindowStyle="None" 
    WindowStartupLocation="CenterOwner"> 

<!-- Allow view models to cause the window to close --> 
<Window.Style> 
    <Style TargetType="{x:Type Window}"> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding IsClosed}" Value="true"> 
       <!-- Executes close --> 
       <Setter Property="attached:WindowCloseBehavior.Close" Value="true" /> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 
</Window.Style> 

<!-- Displays the passed-in view model --> 
<Grid> 
    <ContentPresenter x:Name="DialogPresenter" Content="{Binding}" Margin="0" /> 
</Grid> 
</Window> 

コード表示:

<UserControl x:Class="UserInterface.Views.DialogViews.ObjectSearchView" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:dialogViewModels="clr-namespace:UserInterface.ViewModels.DialogViewModels" 
     xmlns:utils="clr-namespace:WPF.Utils" 
     xmlns:attached="clr-namespace:UserInterface.Attached" 
     mc:Ignorable="d" 
     d:DataContext="{d:DesignInstance dialogViewModels:ObjectSearchViewModel}" 
     MinWidth="250" 
     Focusable="True" 
     FocusManager.IsFocusScope="True"> 
<UserControl.InputBindings> 
    <KeyBinding Key="Enter" Command="{Binding BrowseToObjectCommand}" /> 
    <KeyBinding Key="Escape" Command="{Binding CloseWindowCommand}" /> 
</UserControl.InputBindings> 
<UserControl.Resources> 
    <Style BasedOn="{StaticResource FormTextBlockStyle}" TargetType="TextBlock" /> 
</UserControl.Resources> 

<StackPanel> 
    <TextBox Name="SearchText" 
      Focusable="True" 
      Text="{utils:ValidatingLiveBinding SearchText}" 
      attached:NavigatingListBoxBehavior.LinkedListBox="{Binding ElementName=SearchResults}"> 
    </TextBox> 
    <ScrollViewer HorizontalScrollBarVisibility="Hidden" 
        VerticalScrollBarVisibility="Auto" 
        MaxHeight="400"> 
     <ListBox Name="SearchResults" 
       ItemsSource="{Binding SearchResults}" 
       SelectedItem="{Binding SelectedSearchItem}" 
       Visibility="{Binding HasSearchResults, Converter={StaticResource BooleanToVisibilityConverter}}" 
       attached:ItemsControlProperties.DoubleClickCommand="{Binding BrowseToObjectCommand}" 
       KeyboardNavigation.IsTabStop="False" 
       IsSynchronizedWithCurrentItem="True" /> 
    </ScrollViewer> 
</StackPanel> 
</UserControl> 

そして最後に、コードビハインド私は(私は、Visual Studioに前後に切り替えフォーカスを失わないように、プラスのデバッグコード)フォーカスを取得しようとしようとしているハック:

public partial class ObjectSearchView : UserControl 
{ 
    public ObjectSearchView() 
    { 
     InitializeComponent(); 
     this.Loaded += this.OnLoad; 
    } 

    private void OnLoad(object sender, RoutedEventArgs e) 
    { 
     this.PrintFocusInfo(); 
     FocusManager.SetFocusedElement(FocusManager.GetFocusScope(this), this.SearchText); 
     this.PrintFocusInfo(); 
     this.SearchText.Focus(); 
     this.PrintFocusInfo(); 
     Keyboard.Focus(this.SearchText); 
     this.PrintFocusInfo(); 
    } 

    [Conditional("DEBUG")] 
    private void PrintFocusInfo() 
    { 
     var logicalElement = FocusManager.GetFocusedElement(FocusManager.GetFocusScope(this.SearchText)); 
     Debug.WriteLine("Current logical focus is on '{0}', of type '{1}' ({2})".FormatInvariantCulture((logicalElement as FrameworkElement)?.Name, logicalElement?.GetType().Name, logicalElement)); 
     var focusedElement = Keyboard.FocusedElement; 
     Debug.WriteLine(
      "Current Keyboard Focus is on '{0}', of type '{1}' ({2})".FormatInvariantCulture(
       (focusedElement as FrameworkElement)?.Name, 
       focusedElement.GetType().Name, 
       focusedElement)); 
    } 
} 

出力ウィンドウの内容:

考えられるすべてを含めるようにしましたが、null以外のものを表示するために論理的なフォーカスを得ることはできません。

答えて

1

これは最終的に私のためにこれを修正した動作です。これはなぜか分からないことはまだたくさんありますが、Focusを協力させて問題を抱えている場合、IsVisibleがtrueに設定されているときにキーをキャッチしているように見え、Dispatcherにフォーカスが設定されているように見えますあなたのために。このイベントをテキストボックスのIsVisibleChanged要素にリンクしました(添付の動作を介して)。

private void SetFocusOnVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) 
    { 
     if ((bool)e.NewValue) 
     { 
      this.Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action(() => this.AssociatedObject.Focus())); 
     } 
    } 
関連する問題