2016-04-21 8 views
3

Ich habe ein Textfeld in einer Viewbox. Wenn ich versuche, die Größe des Fensters zu ändern, werden Textboxgröße und Schriftgröße skaliert, aber wenn ich versuche, den Textkasten zu fokussieren und den Cursor mit der Tastatur in das Textfeld zu bewegen, verschwindet manchmal der Cursor. Gibt es eine Möglichkeit, den Cursor immer zu zeigen? Verweisen Sie den folgenden Code, der eine TextBox in ViewBox enthält.WPF TextBox Inside ViewBox verliert den Cursor bei der Größenänderung

<Window x:Class="Resolution_Learning.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow"> 
<Viewbox Stretch="Uniform"> 
    <Grid Width="2560" Height="1440" > 
     <Grid.RowDefinitions> 
      <RowDefinition/> 
      <RowDefinition/> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition/> 
      <ColumnDefinition/> 
      <ColumnDefinition/> 
      <ColumnDefinition/> 
     </Grid.ColumnDefinitions> 
     <Label Grid.Row="0" Grid.Column="0" Content="Hello"/> 
     <TextBox Grid.Row="0" Grid.Column="1"></TextBox> 
     <Label Grid.Row="0" Grid.Column="2" Content="Hello"/> 
     <TextBox Grid.Row="0" Grid.Column="3"/> 
     <Label Grid.Row="1" Grid.Column="0" Content="Hello"/> 
     <TextBox Grid.Row="1" Grid.Column="1"/> 
     <Label Grid.Row="1" Grid.Column="2" Content="Hello"/> 
     <TextBox Grid.Row="1" Grid.Column="3"/> 
    </Grid> 
</Viewbox> 

+0

Zu welchem ​​genauen Schlüssel der Textbox Fokus verliert? –

+0

Versuchen Sie, das Fenster auf kleine Größe zu verkleinern und versuchen Sie, das Textfeld einzugeben. –

+0

Funktioniert gut für mich, aber der Text ist zu klein, um zu sehen. Das Fenster größer zu machen, zeigt den Text, den ich klein geschrieben habe. Seltsames ux imo, warum nicht Scrollbalken? –

Antwort

1

Es ist ein BUG in WPF. Ich habe dies erreicht, indem ich meinen eigenen Stil für TextBoxCaret geschaffen habe.

XAML:Style for TextBox

<Style TargetType="{x:Type TextBox}" x:Key="CaretStyle" > 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate> 
          <Canvas>          
           <TextBox x:Name="Box" CaretBrush="Transparent" Width="{Binding RelativeSource={RelativeSource AncestorType=TextBox},Path=ActualWidth,Mode=OneWay}" 
              Height="{Binding RelativeSource={RelativeSource AncestorType=TextBox},Path=ActualHeight,Mode=OneWay}"/> 
           <Border x:Name="Caret" 
            Visibility="Collapsed" 
            Canvas.Left="0" Canvas.Top="0" Margin="0" Padding="0" 
            Width="1" Height="16" Background="Black">           
            <Border.Triggers> 
             <EventTrigger RoutedEvent="Border.Loaded"> 
              <BeginStoryboard> 
               <Storyboard x:Name="CaretStoryBoard" 
            RepeatBehavior="Forever"> 
                <ColorAnimationUsingKeyFrames 
            Storyboard.TargetProperty="Background.Color" 
            Duration="0:0:0:1" 
            FillBehavior="HoldEnd"> 
                 <ColorAnimationUsingKeyFrames.KeyFrames > 
                  <DiscreteColorKeyFrame KeyTime="0:0:0.750" 
        Value="Transparent" /> 
                  <DiscreteColorKeyFrame KeyTime="0:0:0.000" 
        Value="Black"/> 
                 </ColorAnimationUsingKeyFrames.KeyFrames> 
                </ColorAnimationUsingKeyFrames> 
               </Storyboard> 
              </BeginStoryboard> 
             </EventTrigger>            
            </Border.Triggers> 
           </Border> 
          </Canvas> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
       <EventSetter Event="SelectionChanged" Handler="CustomTextBox_SelectionChanged"/> 
       <EventSetter Event="GotFocus" Handler="CustomTextBox_GotFocus" /> 
       <EventSetter Event="LostFocus" Handler="CustomTextBox_LostFocus" /> 
      </Style> 

EVENTS:For Caret Position

void CustomTextBox_LostFocus(object sender, RoutedEventArgs e) 
    { 
     var Caret = FindChild<Border>(sender as DependencyObject, "Caret"); 
     Caret.Visibility = Visibility.Collapsed; 
    } 

    void CustomTextBox_GotFocus(object sender, RoutedEventArgs e) 
    { 
     var Caret = FindChild<Border>(sender as DependencyObject, "Caret"); 
     Caret.Visibility = Visibility.Visible; 
    } 

    void CustomTextBox_SelectionChanged(object sender, RoutedEventArgs e) 
    { 
     var CustomTextBox = FindChild<TextBox>(sender as DependencyObject, "Box"); 
     var caretLocation = CustomTextBox.GetRectFromCharacterIndex(CustomTextBox.CaretIndex).Location; 
     var Caret = FindChild<Border>(sender as DependencyObject, "Caret"); 
     if (!double.IsInfinity(caretLocation.X)) 
     { 
      Canvas.SetLeft(Caret, caretLocation.X); 
     } 

     if (!double.IsInfinity(caretLocation.Y)) 
     { 
      Canvas.SetTop(Caret, caretLocation.Y); 
     } 
    } 

Helper-Methode:To Get Visual Child

 public static T FindChild<T>(DependencyObject parent, string childName) 
    where T : DependencyObject 
     { 
      // Confirm parent and childName are valid. 
      if (parent == null) return null; 

      T foundChild = null; 

      int childrenCount = VisualTreeHelper.GetChildrenCount(parent); 
      for (int i = 0; i < childrenCount; i++) 
      { 
       var child = VisualTreeHelper.GetChild(parent, i); 
       // If the child is not of the request child type child 
       T childType = child as T; 
       if (childType == null) 
       { 
        // recursively drill down the tree 
        foundChild = FindChild<T>(child, childName); 

        // If the child is found, break so we do not overwrite the found child. 
        if (foundChild != null) break; 
       } 
       else if (!string.IsNullOrEmpty(childName)) 
       { 
        var frameworkElement = child as FrameworkElement; 
        // If the child's name is set for search 
        if (frameworkElement != null && frameworkElement.Name == childName) 
        { 
         // if the child's name is of the request name 
         foundChild = (T)child; 
         break; 
        } 
       } 
       else 
       { 
        // child element found. 
        foundChild = (T)child; 
        break; 
       } 
      } 

      return foundChild; 
     } 

Fügen Sie einfach oben Style/metods in Ihrem Code und setzen Style für TextBoxes wo immer Sie wollen und sehen die Ergebnis. Wie ich dies selbst ohne tatsächliche Messung der tatsächlichen erstellt haben, können Sie einen leichten Schatten in gewissem Umfang sehen. passen Sie bitte das Aussehen & an fühlen Sie sich wie gebraucht.

+0

Gibt es eine Möglichkeit, diesen Schatten zu umgehen? –

+0

@AyyappanSubramanian ja ... gerade hat es ... gesetzt CaretBrush = "Transparent" in der ursprünglichen Textbox ... Ich habe in der Antwort aktualisiert .. Sie können überprüfen ... :) –

+0

@AyyappanSubramanian hat es Ihr Problem lösen? –

1

Was ich denke, hier geschieht, ist dies:

Da alle Bedienelemente im Inneren des ViewBox sind die Größe neu bestimmt, die caret nicht immer aufgrund von Pixel Berechnungen gezogen wird.

Damit es funktioniert, müssen wir unsere eigenen Caret erstellen. Ich habe das Internet durchsucht, falls jemand dies bereits implementiert hat, und THIS Artikel von d.moncada gefunden.

Ich habe den Quellcode heruntergeladen und verwendet, um die CustomCaretTextBox (statt der regulären TextBox) zu testen, ob es das Problem zu lösen, und es tat!

Ich empfehle Ihnen dringend, die Lösung zu versuchen, da es elegant aussieht, funktioniert aus der Box und kann leicht von Ihren Bedürfnissen manipuliert werden.

Happy Coding! :)

0

Ich konnte das Problem beheben, indem Sie den Stil von TextBox machen Stretched wie folgt:

<Style x:Name="TextBoxStyleTitle" 
      TargetType="TextBox"> 
     <Setter Property="VerticalAlignment" 
       Value="Stretch"></Setter> 
     <Setter Property="HorizontalAlignment" 
       Value="Stretch"></Setter> 
</Style>