iNKORE-NET / UI.WPF.Modern

Modern (Fluent 2) styles and controls for your WPF applications
https://docs.inkore.net/ui-wpf-modern
GNU Lesser General Public License v2.1
326 stars 29 forks source link

Unable to make TextBox to auto scroll to bottom when it's being updated. #34

Open kevwkev opened 5 months ago

kevwkev commented 5 months ago

The ScrollToEnd() function appears ineffective with TextBox, tested in both code-behind and MVVM utilizing a behavior extension of the TextBox control.

===code-hehind===

  1. Use x:name. Subscribed to TextChanged event.
  2. Call textbox.ScrollToEnd() in TextChanged event.

===behavior extension for MVVM====

public class ScrollToEndBehavior
{
    public static readonly DependencyProperty OnTextChangedProperty =
                DependencyProperty.RegisterAttached(
                "OnTextChanged",
                typeof(bool),
                typeof(ScrollToEndBehavior),
                new UIPropertyMetadata(false, OnTextChanged)
                );

    public static bool GetOnTextChanged(DependencyObject dependencyObject)
    {
        return (bool)dependencyObject.GetValue(OnTextChangedProperty);
    }

    public static void SetOnTextChanged(DependencyObject dependencyObject, bool value)
    {
        dependencyObject.SetValue(OnTextChangedProperty, value);
    }

    private static void OnTextChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        var textBox = dependencyObject as TextBox;
        var newValue = (bool)e.NewValue;

        if (textBox == null || (bool)e.OldValue == newValue)
        {
            return;
        }

        TextChangedEventHandler handler = (object sender, TextChangedEventArgs args) =>
            ((TextBox)sender).ScrollToEnd();

        if (newValue)
        {
            textBox.TextChanged += handler;
        }
        else
        {
            textBox.TextChanged -= handler;
        }
    }
} 
NotYoojun commented 5 months ago

Hi! Thank you for reporting this. It seems that this is the problem made by the control ScollViewerEx.cs. I'll check that later cuz I'm in the weeds right now. 😕

NotYoojun commented 5 months ago

Help needed! I can't solve this after a few attempts.

Zaitonn commented 5 months ago

https://github.com/iNKORE-Public/UI.WPF.Modern/blob/89322a8d2d41683d42e9f623ee6129ac1c46ab58/source/iNKORE.UI.WPF.Modern/Controls/ScrollViewerEx.cs#L106-L115

这段注释掉就正常了,但是不知道有无副作用 有点难评但是管用

个人感觉是ScrollInfoAdapter.SetVerticalOffset(double offset)执行动效的时候寄了

Zaitonn commented 5 months ago

https://github.com/iNKORE-Public/UI.WPF.Modern/blob/89322a8d2d41683d42e9f623ee6129ac1c46ab58/source/iNKORE.UI.WPF.Modern/Themes/Styles/TextBox.xaml#L148-L163

(把ScrollViewerEx改成ScrollViewer也能正常滚到末尾

NotYoojun commented 4 months ago

把 ScrollViewerEx 改成 ScrollViewer 的方案是不可取的。ScrollViewerEx 存在的意义就是修复和优化 WPF 自带的垃圾滚动逻辑。我们解决这个问题只能从 ScrollViewer 本身下手。

Byolock commented 2 months ago

I don't know how far your testing did go, I just realized both functions ScrollToHomeand ScrollToEnddo work a single time after the application is started. Then I found out they work again after the contrary function is called, meaning a not working ScrollToEnd function does work again after ScrollToHome is called once.

In conclusion there is at least a workaround for now, just call ScrollToHome everytime before you call ScrollToEnd. It works in my test project, within a slower program or an a slower machine, adding texts fast, I would imaging this approach to be problemtic though.