2017-03-07 29 views
1

我已经为此挣扎了好几天 - Google无济于事。迷失焦点之谜 - 无法将其元素从其附加行为中集中

我有一个RichTextBox正在装饰InkCanvas。笔画从InkCanvas收集并识别。当装饰器关闭时,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; 
     } 

那么什么是需要魔法焦点返回到RichTextControl完成在装饰器中使用InkCanvas后?

我真的非常感谢任何帮助(在我完全秃顶之前)!

TIA

+1

你的意思是(''uie.Focus();'')执行,但返回false或应用程序永远不会到达这部分?另外,请使用''Keyboard.focus(uie)''让我们知道结果。谢谢。 – Ron

+0

@Ron在上面的代码中,代码隐藏从未接收到焦点,如GotFocus事件从未被调用所示。尽管uie.Focus()正在执行(并且正确解析为RichTextBox)。但我确实发现了我的问题。谢谢。 –

回答

0

我尝试使用Snoop 2.8.0没有多少运气(我找不到焦点事件)。但是,将

UIElement elementWithFocus = Keyboard.FocusedElement as UIElement; 

在不同的点约于uie.Focus()调用很快表明,ScrollViewer中被接收的重点,而不是RichTextBox的。进一步的研究很快显示,在调用uie.Focus()时,RichTextBox Visibility已被设置为Hidden。

在调用uie.Focus()修复所有问题之前,确保将RichTextBox可见性设置为Visible。

获得的经验:显然元素必须在它能够获得焦点之前可见!

相关问题