
Hi, I am using SyntaxEditor as a logging kind of control where new text is constantly added to the end. In relation to this I also want the SyntaxEditor control to always scroll to the bottom. I have tried a lot of different ways, how can I do this? This is my current code
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:syntaxeditor="http://schemas.actiprosoftware.com/winfx/xaml/syntaxeditor"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Click="ButtonBase_OnClick" Grid.Row="0" Width="50" Content="Run" />
<syntaxeditor:SyntaxEditor Grid.Row="1" x:Name="TestRunFeedbackBox" CanScrollPastDocumentEnd="False" IsWordWrapEnabled="True" IsDocumentReadOnly="True" DocumentTextChanged="TestRunFeedbackBox_OnDocumentTextChanged" FontFamily="Consolas" Background="{DynamicResource Control.EditorBackgroundBrush}" Foreground="{DynamicResource Control.ForegroundBrush}" Text="{Binding Text}" />
</Grid>
</Window>
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using ActiproSoftware.Text;
using ActiproSoftware.Windows.Controls.SyntaxEditor;
namespace WpfApp1
{
public partial class MainWindow : Window
{
private ViewModel _viewModel;
public MainWindow()
{
InitializeComponent();
_viewModel = new ViewModel();
DataContext = _viewModel;
}
private void TestRunFeedbackBox_OnDocumentTextChanged(object? sender, EditorSnapshotChangedEventArgs e)
{
var lineCount = TestRunFeedbackBox.Document.CurrentSnapshot.Lines.Count;
TestRunFeedbackBox.ActiveView.Selection.CaretPosition = new TextPosition(lineCount - 1, 5);
TestRunFeedbackBox.ActiveView.Scroller.ScrollToCaret();
TestRunFeedbackBox.ActiveView.Scroller.ScrollToDocumentEnd();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
Task.Run(() =>
{
for (int i = 0; i < 10000; i++)
{
Application.Current.Dispatcher.Invoke(() => _viewModel.Text += $"{i}\r\n");
Thread.Sleep(50);
}
});
}
}
public class ViewModel : INotifyPropertyChanged
{
private string _text;
public string Text
{
get => _text;
set => Set(_text, value, v => _text = v);
}
public event PropertyChangedEventHandler? PropertyChanged;
private void RaisePropertyChanged(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
private void Set<T>(T oldValue, T newValue, Action<T> setValue, [CallerMemberName] string propertyName = "")
{
if ((oldValue == null && newValue != null) || (oldValue != null && !oldValue.Equals(newValue)))
{
setValue(newValue);
RaisePropertyChanged(propertyName);
}
}
}
}