2017-03-07 10 views
1

私は今これで数日間苦労しています。ロストフォーカスの謎 - 添付された行動から要素を集めることができません

私は、RichTextBoxをInkCanvasで飾っています。ストロークは、InkCanvasから収集され、認識されます。 adornerが閉じられると、RichTextBoxのアタッチされた動作が明示的に使用され、RichTextBoxにフォーカスが戻されます。しかし、RichTextBoxをフォーカスする明示的な呼び出しにもかかわらず、RichTextBoxは信号を受け取ることはありません。

何が起こっているのですか、どうすれば解決できますか?

はTIA

XAML

 <ScrollViewer Grid.Row ="2" Grid.Column="1" VerticalScrollBarVisibility="Auto" > 
      <!--ScrollViewer can only have one child.--> 
      <Grid> 

     ........................................ 

<!-- 
        XAML that creates the adorned control and the adorner 
       --> 
       <ac:AdornedControl IsAdornerVisible="{Binding TranscriptionLayer.IsAdornerVisible}" Grid.ColumnSpan="2"> 
        <!--#region Adorned Element--> 
        <!-- 
         TranscriptionLayer will have an Adorner (inkcanvas) for handwriting recogntion. 
         The RichTextBox is the element being adorned and sets the size of the adornment object (i.e., 
         the inkcanvas writing surface). The RichTextControl holds the actual transcript. 
        --> 
        <RichTextBox x:Name="RichTextControl" Panel.ZIndex="{Binding TranscriptionLayer.ZIndex}" 
           Height="{Binding VirtualPage.Height}" 
           Visibility="{Binding TranscriptionLayer.TranscriptIsVisible}" 
          SpellCheck.IsEnabled="True" 
          VerticalScrollBarVisibility="Auto" 
          AcceptsReturn="True" AcceptsTab="True" 
          > 
         <!--Remove blank line between paragraphs--> 
         <RichTextBox.Resources> 
          <Style TargetType="{x:Type Paragraph}"> 
           <Setter Property="Margin" Value="0"/> 
          </Style> 
         </RichTextBox.Resources> 

         <i:Interaction.Behaviors> 
          <!--Update the menu and toolbar when a selection is made in the RichTextBox--> 
          <!--The behavior is bound to the SelectionChanged of the RichTextBox. 
          <b:RichTextBehavior AlignLeft ="{Binding TranscriptionLayer.AlignLeft}" /> --> 
          <b:RichTextBehavior 
           FontHeight="{Binding ElementName=Fontheight, Path=SelectedItem, Mode=TwoWay, Converter={c:NullToDoubleConverter}}" 
           TextFont="{Binding ElementName=Fonttype,  Path=SelectedItem}" 
           TextBold="{Binding ElementName=ToggleBold, Path=IsChecked}" 
           Italic="{Binding ElementName=ToggleItalic, Path=IsChecked}" 
           Underline="{Binding ElementName=ToggleUnderline, Path=IsChecked}" 
           Strikethrough="{Binding ElementName=ToggleStrikethrough, Path=IsChecked}" 
           ParagraphTag ="{Binding ElementName=CurrentParagraph, Path=SelectedItem}" 
           SelectedText="{Binding TranscriptionLayer.SelectedText}" 
           IsFocused ="{Binding TranscriptionLayer.RichTextHasFocus}" 
          /> 
         </i:Interaction.Behaviors> 

        </RichTextBox> 


        <!--#endregion--> 
        <ac:AdornedControl.AdornerContent> 
         <!--#region The Adorner--> 
         <!-- This is the framework element as the adorner content. It is always on top of the adorned element. There adorned elements 
          is the RichTextConttrol. 
          The ItemsControl will expand to the width of the parent adorner which takes its size from the adorned element-the 
          RichTextConttrol. The ItemsControl inherits from  System.Windows.FrameworkElement. 
         --> 

          <ItemsControl x:Name="WritingLayerControl" ItemsSource="{Binding TranscriptionLayer.WritingBoxes}" > 
           <!-- 
           If the <ItemsControl.ItemsPanel> is not used, the ItemsControl will default to a vertical StackPanel. 
          --> 

           <ItemsControl.ItemTemplate> 
            <!-- 
           DataTemplate and DataType point to a class, not a namespace! 
          --> 
            <DataTemplate DataType="{x:Type vm:WritingBoxViewModel}" > 
             <Grid> 
              <Grid.RowDefinitions> 
               <!-- 0 to be used for recogntion results--> 
               <RowDefinition Height="auto" /> 
               <!-- 1 to be used for Ink --> 
               <RowDefinition Height="auto"/> 
              </Grid.RowDefinitions> 

              <TextBlock Grid.Row="0" Text="{Binding RecognitionResults}" Background="#100000FF" 
                Height="{Binding RecognitionResultsHeight}"/> 

              <!--  
            Binding Mode must be set to TwoWay on TheSelectedStrokes because by default binding works one way, 
            i.e. loading changes from the view model, but not updating the viewmodel back. So either use: 
            TheSelectedStrokes="{Binding SelectedStrokes, Mode=TwoWay}" or set it with 
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault in TheSelectedStrokes dependency definition. 

            Background is of type Brush, so must use ImageBrush, DrawingBrush, VisualBrush. 
            --> 

              <InkCanvas x:Name="InkCanvas" Grid.Row="1" 
             Height="{Binding WritingBoxHeight}" Strokes="{Binding Strokes}" 
             EditingMode="{Binding EditingMode}" 
             DefaultDrawingAttributes="{Binding DefaultDrawingAttributes}" > 

               <i:Interaction.Behaviors> 
                <b:InkCanvasBehavior DeletedStrokes="{Binding DrawingLayer.DeleteStrokes}" /> 
               </i:Interaction.Behaviors> 

               <InkCanvas.Background> 
                <!-- 
             Note: Making the DrawingBrush a StaticResource makes the XAML much more efficient as only one object 
              is created. It also is only created on the first pass and no update from the Bindings will happen so 
              the lines will not change even when the TypeSize is changed. 

             Viewport (type Rect) gives the position, width, and height of the base tile 
             --> 
                <DrawingBrush Stretch="Uniform" TileMode="Tile" Viewport="{Binding ViewPortBaseTile}" ViewportUnits="Absolute" > 
                 <DrawingBrush.Drawing> 
                  <GeometryDrawing> 
                   <GeometryDrawing.Geometry> 
                    <GeometryGroup> 
                     <!-- 
                  X is horizontal displacement from origin. 
                   Y is veritcal displacyement from origin. 
                   Origin O(0,0) is top-left of InkCanvas. 
                  --> 

                     <!-- Vertical Line 
                   <LineGeometry StartPoint="0,0" EndPoint="{Binding TileBottom}"/> 
                  --> 
                     <!-- Midline. Horizontal Line --> 
                     <LineGeometry StartPoint="{Binding MidLineStartPoint}" EndPoint="{Binding MidLineEndPoint}"/> 

                     <!-- BaseLine. Horizontal Line--> 
                     <LineGeometry StartPoint="{Binding BaseLineStartPoint}" EndPoint="{Binding BaseLineEndPoint}"/> 
                    </GeometryGroup> 

                   </GeometryDrawing.Geometry> 
                   <GeometryDrawing.Pen> 
                    <Pen Thickness="1" Brush="Tomato"/> 
                   </GeometryDrawing.Pen> 

                  </GeometryDrawing> 
                 </DrawingBrush.Drawing> 
                </DrawingBrush> 
               </InkCanvas.Background> 
              </InkCanvas> 

             </Grid> 
            </DataTemplate> 
           </ItemsControl.ItemTemplate> 
          </ItemsControl> 

         <!--#endregion--> 
        </ac:AdornedControl.AdornerContent> 
       </ac:AdornedControl> 
      </Grid> 
     </ScrollViewer> 

C#

namespace Behaviors 
{ 
    public class RichTextBehavior : Behavior<RichTextBox> 
    { 
     protected override void OnAttached() 
     { 
      base.OnAttached(); 
      AssociatedObject.SelectionChanged += RichTextBoxSelectionChanged; 
      AssociatedObject.TextChanged += RichTextBoxTextChanged; 
     } 

     protected override void OnDetaching() 
     { 
      base.OnDetaching(); 
      AssociatedObject.SelectionChanged -= RichTextBoxSelectionChanged; 
      AssociatedObject.TextChanged -= RichTextBoxTextChanged; 
     } 

.................................................... 

public static bool GetIsFocused(DependencyObject obj) 
     { 
      return (bool)obj.GetValue(IsFocusedProperty); 
     } 

     public static void SetIsFocused(DependencyObject obj, bool value) 
     { 
      obj.SetValue(IsFocusedProperty, value); 
     } 

     public static readonly DependencyProperty IsFocusedProperty = 
      DependencyProperty.RegisterAttached(
       "IsFocused", typeof(bool), typeof(RichTextBehavior), 
       new UIPropertyMetadata(false, OnIsFocusedPropertyChanged)); 

     private static void OnIsFocusedPropertyChanged(
      DependencyObject d, 
      DependencyPropertyChangedEventArgs e) 
     { 
      var behavior = d as RichTextBehavior; 

      var uie = (UIElement)behavior.AssociatedObject; 
      if ((bool)e.NewValue) 
      { 
       uie.Focus(); // Don't care about false values. 
      } 
     } 

最後の行、uie.Focus()が正しく実際の制御に到達していない - しかしRichTextBoxControlに解決します!

これは、コードビハインド「のGotFocus()」イベントと呼ばれていないされないことによって実証されています

コードビハインド

public partial class ProgressNotesView : UserControl 
    { 
     public ProgressNotesView() 
     { 
      InitializeComponent(); 
      RichTextControl.GotFocus += RichTextControl_GotFocus; 
      RichTextControl.LostFocus += RichTextControl_LostFocus; 

      Loaded += (s, e) => 
      { 
       // When used as a UserControl as Data first, the DataContext has already been set to the ViewModel 
       // before the UserControl is Initialized. 
       vm = (ProgressNoteViewModel)DataContext; 
       Fontheight.SelectedItem = 12.0; 
      }; 
     } 

     private void RichTextControl_LostFocus(object sender, RoutedEventArgs e) 
     { 
      var y = 10; 
     } 

     private void RichTextControl_GotFocus(object sender, RoutedEventArgs e) 
     { 
      var x = 10; 
     } 

そうにフォーカスを返すためにどのような魔法を必要とされています私がAdornerでInkCanvasの使用を終えたら、RichTextControl?

私は本当に大変感謝しています。

TIA

+1

( '' uie.Focus(); '')が実行されますが、falseを返すか、アプリケーションがこの部分に到達しないことを意味しますか?また、 '' Keyboard.focus(uie) ''を使って結果をお知らせください。ありがとう。 – Ron

+0

@Ron上記のコードでは、コードビハインドは決して呼び出されないGotFocusイベントによって示されるようにフォーカスを受け取ることはありませんでした。これはuie.Focus()が実行されているにもかかわらず(そして、RichTextBoxに正しく解決されています)。私は私の問題を見つけた。ありがとう。 –

答えて

0

私は(私はフォーカスイベントを見つけることができませんでした)多くの幸運なしSnoop 2.8.0を使用してみました。しかし、uie.Focus()呼び出しarroundの様々な点で

UIElement elementWithFocus = Keyboard.FocusedElement as UIElement; 

を確定を迅速ScrollViewerのフォーカスではなく、リッチテキストボックスを受信したことを示しました。さらに調査したところ、uie.Focus()が呼び出された時点で、RichTextBox VisibilityがHiddenに設定されていたことがすぐにわかりました。

uie.Focus()を呼び出す前にRichTextBoxの可視性がVisibleに設定されていることを確認し、すべての問題を修正しました。

教訓:明らかに、フォーカスを受け取るには要素が表示されている必要があります。

関連する問題