0

テキストが追加されたときに最後まで自動スクロールするテキストボックスを作成しています。ただし、マウスがテキストボックスの上にあるときにテキストボックスをスクロールしないオプションが必要でした。私はそれをすべてやりましたが、ユーザーがテキストを選択し、テキストボックスがテキストを更新するイベントを受け取ると、すべてがうまくいきません。

これが私が取り組んでいるものです:


<TextBox Text="{Binding ConsoleContents, Mode=OneWay}" TextWrapping="Wrap" 
    IsReadOnly="True" ScrollViewer.VerticalScrollBarVisibility="Visible" 
    TextChanged="TextBox_TextChanged" MouseEnter="TextBox_MouseEnterLeave"
    MouseLeave="TextBox_MouseEnterLeave" AllowDrop="False" Focusable="True" 
    IsUndoEnabled="False"></TextBox>

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        if (textBox == null) return;

        // ensure we can scroll
        if (_canScroll)
        {
            textBox.Select(textBox.Text.Length, 0); //This was an attempt to fix the issue
            textBox.ScrollToEnd();
        }
    }

private void TextBox_MouseEnterLeave(object sender, MouseEventArgs e)
    {
        TextBox textBox = sender as TextBox;

        // Don't scroll if the mouse is in the box
        if (e.RoutedEvent.Name == "MouseEnter")
        {
            _canScroll = false;
        }
        else if (e.RoutedEvent.Name == "MouseLeave") 
        {
            _canScroll = true;
        }
    }

haywire の意味をさらに説明すると、テキストボックスがプロパティ変更イベントを受け取ると、テキストが設定され、マウスがその上にない場合は最後までスクロールします。マウスが上にある場合、スクロールしません。しかし、テキストを選択し、テキスト ボックスが propertychanged イベントを受け取ると、コンテンツは更新されますが、ボックスは下にスクロールしません。これは予期されることです。問題は、カーソルが現在ある場所からテキストの上部に選択が移動することです。ボックスからカーソルを削除すると、問題なく続行されますが、カーソルが戻ると、ボックスが上部で動かなくなり、下にスクロールできなくなります。カーソルだったのではないかと思ったので、最後に移動しようとしましたが、何も解決しません。

何か案は?!

髪をかきあげてきました!ありがとう!

4

2 に答える 2

0

PropertyChanged イベントの余分なケースを処理する必要があります。テキストが変更されるため、コントロールが更新されます。更新されるため、カーソル位置や選択したテキストなどの特定の値がリセットされます。

CaretIndexSelectionStartおよびのように、これらの設定を一時的に保存することができますSelectionLength。私はこれについて経験がないので、どの値を維持したいかを自分で見つける必要があります。

TextBox に対して PropertyChanged イベントがトリガーされたときに、同じ_canScrollチェックを適用することもできます。これにより、テキストを操作できます。ただし、マウスが Textbox から離れた場合、最新のテキストが表示される前に新しいイベントを待つ必要があります。

また、プロパティの使用を検討することもできIsFocusedます。私の意見では、MouseEnter および MouseLeave イベントよりも優れたソリューションを提供します。しかし、それはもちろんあなた次第です。

于 2012-10-23T19:10:12.713 に答える
0

午前中いっぱいかかりましたが、その方法は次のとおりです。

<TextBox Text="{Binding ConsoleContents, Mode=OneWay}" 
         TextWrapping="Wrap" IsReadOnly="True" ScrollViewer.VerticalScrollBarVisibility="Visible" TextChanged="TextBox_TextChanged" 
         MouseEnter="TextBox_MouseEnterLeave" MouseLeave="TextBox_MouseEnterLeave" SelectionChanged="TextBox_SelectionChanged" AllowDrop="False" Focusable="True" 
         IsUndoEnabled="False"></TextBox>

public partial class ConsoleView : UserControl
{
    private bool _canScroll;

    // saves
    private int _selectionStart;
    private int _selectionLength;
    private string _selectedText;

    public ConsoleView(ConsoleViewModel vm)
    {
        InitializeComponent();
        this.DataContext = vm;

        _canScroll = true;
    }


    private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        if (textBox == null) return;

        // ensure we can scroll
        if (_canScroll)
        {
            // set the cursor to the end and scroll down
            textBox.Select(textBox.Text.Length, 0);
            textBox.ScrollToEnd();

            // save these so the box doesn't jump around if the user goes back in
            _selectionLength = textBox.SelectionLength;
            _selectionStart = textBox.SelectionStart;
        }
        else if (!_canScroll)
        {

            // move the cursor to where the mouse is if we're not selecting anything (for if we are selecting something the cursor has already moved to where it needs to be)
            if (string.IsNullOrEmpty(_selectedText))
            //if (textBox.SelectionLength > 0)
            {
                textBox.CaretIndex = textBox.GetCharacterIndexFromPoint(Mouse.GetPosition(textBox), true);
            }
            else
            {
                textBox.Select(_selectionStart, _selectionLength); // restore what was saved
            }

        }
    }


    private void TextBox_MouseEnterLeave(object sender, MouseEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        if (textBox == null) return;

        // Don't scroll if the mouse is in the box
        if (e.RoutedEvent.Name == "MouseEnter")
        {
            _canScroll = false;
        }
        else if (e.RoutedEvent.Name == "MouseLeave")
        {
            _canScroll = true;
        }

    }


    private void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        if (textBox == null) return;

        // save all of the things
        _selectionLength = textBox.SelectionLength;
        _selectionStart = textBox.SelectionStart;
        _selectedText = textBox.SelectedText; // save the selected text because it gets destroyed on text update before the TexChanged event.

    }

}
于 2012-10-24T16:08:55.170 に答える