切换两个WPF TextBoxes和ScrollToEnd()的内容

时间:2015-03-27 20:25:57

标签: c# wpf

我试图切换两个WPF文本框的文本,将插入符号设置为每个TextBox的末尾,并将这些插入符号位置滚动到视图中(这样每个TextBox的最后一个字符仍然可见)。

这是Window的简单版本:

<Window ...>
    <StackPanel>
        <TextBox x:Name="textBox1" Text="aaabbbcccd" Height="25" Width="100" Margin="2" />
        <TextBox x:Name="textBox2" Text="aaaaabbbbbcccccd" Height="25" Width="100" Margin="2" />
        <Button Content="Switch text" Width="70" Margin="4" Click="OnClick_button_switchText" />
    </StackPanel>
</Window>

这是点击事件的代码隐藏:

private void OnClick_button_switchText( object sender, RoutedEventArgs e )
{
     // Switch text
     string text1  = textBox1.Text;
     textBox1.Text = textBox2.Text;
     textBox2.Text = text1;

     // Scroll to last characters
     textBox1.ScrollToEnd();
     textBox2.ScrollToEnd();
}

不幸的是,ScrollToEnd()没有按预期工作:没有任何反应。因此,我也尝试了其他几种可能性 - 这些也没有做任何事情,直到我开始设定焦点:

private void OnClick_button_switchText( object sender, RoutedEventArgs e )
{
    ...

    // 2nd try
    textBox1.Focus();
    textBox1.CaretIndex = textBox1.Text.Length;
    textBox2.Focus();
    textBox2.CaretIndex = textBox2.Text.Length;

    // 3rd try
    textBox1.Focus();
    EditingCommands.MoveToLineEnd.Execute( null, textBox1 );
    textBox2.Focus();
    EditingCommands.MoveToLineEnd.Execute( null, textBox2 );

    // 4th try
    textBox1.Focus();
    Rect a_charIndexRect = textBox1.GetRectFromCharacterIndex( textBox1.CaretIndex );
    textBox1.ScrollToHorizontalOffset( a_charIndexRect.Right );
    textBox2.Focus();
    a_charIndexRect = textBox2.GetRectFromCharacterIndex( textBox2.CaretIndex );
    textBox2.ScrollToHorizontalOffset( a_charIndexRect.Right );
}

如果焦点设置在实际滚动方法之前它几乎可以工作(第二和第三种可能):textBox2正确显示文本,但textBox1仍然不滚动到结尾 - 但它确实将插入符号设置为结束。
如果按Tab键聚焦此控件,您会注意到光标位于末尾,但不在视野范围内。

所以我认为这可能是某种时间问题,并尝试在&#34; GotFocus&#34;内执行相应的滚动方法。 TextBoxes的事件,但没有任何成功。

有没有办法切换两个TextBox的文本并仍然显示最后的字符?
任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

经过几次尝试和Peter Duniho发布的提示后,我发现了如何做到这一点 请注意,这仍然不是一个完美的解决方案,因为它不是MVVM方法 - 而是一种工作方式。
如果要在滚动到结尾后聚焦其中一个TextBox,则必须使用不同的方法:

private void OnClick_button_switchText( object sender, RoutedEventArgs e )
{
     // Switch text
     string text1  = textBox1.Text;
     textBox1.Text = textBox2.Text;
     textBox2.Text = text1;

     // Scroll to end - without focus
     textBox1.ScrollToHorizontalOffset( double.PositiveInfinity );
     textBox2.ScrollToHorizontalOffset( double.PositiveInfinity );

     // Scroll to end - and focus the first TextBox
     textBox1.Focus();
     EditingCommands.MoveToLineEnd.Execute( null, textBox1 );
     textBox2.ScrollToHorizontalOffset( double.PositiveInfinity );

     // Scroll to end - and focus the second TextBox
     textBox1.ScrollToHorizontalOffset( double.PositiveInfinity );
     textBox2.Focus();
     EditingCommands.MoveToLineEnd.Execute( null, textBox2 );
}

编辑:这是我的MVVM方法(我保留现有的焦点)

<Window ...>
    <StackPanel>
        <TextBox x:Name="textBox1" Text="{Binding Text1}" behaviors:TextBoxScrollToEndBehavior.ScrollToEndOnEnabledBehavior="True" Height="25" Width="100" Margin="2"/>
        <TextBox x:Name="textBox2" Text="{Binding Text2}" behaviors:TextBoxScrollToEndBehavior.ScrollToEndOnEnabledBehavior="True" Height="25" Width="100" Margin="2"/>
        <Button Content="Switch text" Width="70" Margin="4" Command="{Binding CommandSwitchText}" />
    </StackPanel>
</Window>

视图模型:

using Behaviors;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;

namespace ViewModels
{
   class MainWindowViewModel : ObservableObject
   {
      public MainWindowViewModel()
      {
         CommandSwitchText = new RelayCommand( SwitchText );
      }


      public RelayCommand CommandSwitchText
      {
         get;
         private set;
      }


      private void SwitchText()
      {
         TextBoxScrollToEndBehavior.IsActive = true;

         string textTemp = Text1;
         Text1 = Text2;
         Text2 = textTemp;

         TextBoxScrollToEndBehavior.IsActive = false;
      }


      private string _text1 = "aaabbbcccd";
      public string Text1
      {
         get
         {
            return _text1;
         }
         set
         {
            _text1 = value;
            RaisePropertyChanged();
         }
      }


      private string _text2 = "aaaaabbbbbcccccd";
      public string Text2
      {
         get
         {
            return _text2;
         }
         set
         {
            _text2 = value;
            RaisePropertyChanged();
         }
      }
   }
}

行为:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace Behaviors
{
   public static class TextBoxScrollToEndBehavior
   {
      private static bool _isActive = false;
      public static bool IsActive
      {
         get
         {
            return _isActive;
         }
         set
         {
            _isActive = value;
         }
      }




      public static readonly DependencyProperty ScrollToEndOnEnabledBehavior = 
         DependencyProperty.RegisterAttached( "ScrollToEndOnEnabledBehavior",
                                              typeof( bool ),
                                              typeof( TextBoxScrollToEndBehavior ),
                                              new UIPropertyMetadata( false, OnScrollToEndOnEnabledBehavior ) );




      public static bool GetScrollToEndOnEnabledBehavior( DependencyObject obj )
      {
         return (bool)obj.GetValue( ScrollToEndOnEnabledBehavior );
      }




      public static void SetScrollToEndOnEnabledBehavior( DependencyObject obj, bool value )
      {
         obj.SetValue( ScrollToEndOnEnabledBehavior, value );
      }




      private static void OnScrollToEndOnEnabledBehavior( object sender, DependencyPropertyChangedEventArgs e )
      {
         TextBox textBox = sender as TextBox;
         if( textBox != null )
         {
            bool isEnabled = (bool)e.NewValue;
            if( isEnabled )
            {
               textBox.TextChanged += OnTextChanged_textBox;
            }
            else
            {
               textBox.TextChanged -= OnTextChanged_textBox;
            }
         }
      }




      static void OnTextChanged_textBox( object sender, TextChangedEventArgs e )
      {
         TextBox textBox = sender as TextBox;
         if( null != textBox )
         {
            if( IsActive )
            {
               if( textBox.IsFocused )
               {
                  EditingCommands.MoveToLineEnd.Execute( null, textBox );
               }
               else
               {
                  textBox.ScrollToHorizontalOffset( double.PositiveInfinity );
               }
            }
         }
      }
   }
}