質問させてください。
コンソール画面(ターミナル画面)のような、テキスト文字を出力する度にスクロールするウインドウを作成したいと思っています。
ある程度まではスクロールバーで過去の情報も表示しつつ、全てをTextBoxで保持するとメモリを消費し過ぎるので、どこかで最近の情報だけに
したいと思います。
バッファが溜まれば削除以外に何か良い方法はありますか?
開発環境:Visual Studio 2017 (WPF)
動作環境:Windows10
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答7件
0
以下の記事が参考になると思います。
記事の中で紹介されているサンプルコード
WPF で Windows PowerShell コンソールを再現します。
投稿2019/03/08 11:01

退会済みユーザー
総合スコア0
0
ベストアンサー
たとえばこんな感じに ListBox と ObservableCollection<string> をバインドし、ObservableCollection の方にリミットをつけておけばいいのではないかと。
C#
1using System; 2using System.Collections.Generic; 3using System.Collections.ObjectModel; 4using System.ComponentModel; 5using System.Runtime.CompilerServices; 6using System.Windows.Input; 7 8namespace WpfApp1 9{ 10 public class ViewModel : INotifyPropertyChanged 11 { 12 public ViewModel() 13 { 14 EnterCommand = new ActionCommand(() => List.Add(CommandLine)); 15 } 16 17 public event PropertyChangedEventHandler PropertyChanged; 18 19 protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null) 20 { 21 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 22 } 23 24 protected bool SetProperty<T>(ref T field, T value, [CallerMemberName]string propertyName = null) 25 { 26 if (EqualityComparer<T>.Default.Equals(field, value)) return false; 27 field = value; 28 OnPropertyChanged(propertyName); 29 return true; 30 } 31 32 private string commandLine; 33 public string CommandLine 34 { 35 get => commandLine; 36 set => SetProperty(ref commandLine, value); 37 } 38 39 private ActionCommand enterCommand; 40 public ActionCommand EnterCommand 41 { 42 get => enterCommand; 43 set => SetProperty(ref enterCommand, value); 44 } 45 46 public OverflowableList List { get; } = new OverflowableList(); 47 } 48 49 public class ActionCommand : ICommand 50 { 51 public ActionCommand(Action action) 52 { 53 Action = action; 54 } 55 56 public Action Action { get; private set; } 57 58 public bool CanExecute(object parameter) 59 { 60 return true; 61 } 62 63 public void Execute(object parameter) 64 { 65 Action(); 66 } 67 68 public event EventHandler CanExecuteChanged; 69 } 70 71 public class OverflowableList : ObservableCollection<string> 72 { 73 protected bool SetProperty<T>(ref T field, T value, [CallerMemberName]string propertyName = null) 74 { 75 if (EqualityComparer<T>.Default.Equals(field, value)) return false; 76 field = value; 77 OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 78 return true; 79 } 80 81 protected virtual void Shrink() 82 { 83 while (Limit < Count) RemoveAt(0); 84 } 85 86 private int limit = 10; 87 public int Limit 88 { 89 get => limit; 90 set 91 { 92 if (SetProperty(ref limit, value)) 93 { 94 Shrink(); 95 } 96 } 97 } 98 99 protected override void InsertItem(int index, string item) 100 { 101 base.InsertItem(index, item); 102 Shrink(); 103 } 104 } 105} 106
XAML
1<Window x:Class="WpfApp1.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:WpfApp1" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="450" Width="800"> 9 <Window.DataContext> 10 <local:ViewModel/> 11 </Window.DataContext> 12 <Grid> 13 <Grid.RowDefinitions> 14 <RowDefinition/> 15 <RowDefinition Height="Auto"/> 16 </Grid.RowDefinitions> 17 <ListBox Grid.Row="0" ItemsSource="{Binding List}" ScrollViewer.HorizontalScrollBarVisibility="Disabled"> 18 <ListBox.ItemTemplate> 19 <DataTemplate> 20 <TextBlock TextWrapping="Wrap" Text="{Binding}"/> 21 </DataTemplate> 22 </ListBox.ItemTemplate> 23 </ListBox> 24 <Grid Grid.Row="1"> 25 <Grid.ColumnDefinitions> 26 <ColumnDefinition/> 27 <ColumnDefinition Width="Auto"/> 28 </Grid.ColumnDefinitions> 29 <TextBox Grid.Column="0" Text="{Binding CommandLine}"/> 30 <Button Grid.Column="1" Command="{Binding EnterCommand}">Click</Button> 31 </Grid> 32 </Grid> 33</Window> 34
投稿2019/03/08 11:58
編集2019/03/11 02:18総合スコア28675
0
WindowsFormでやってる方法ですが(WPFでできるかどうかはわかりませんが)
TextBoxで追記していって、ある程度溜まった場合に(数M文字)、先頭からその容量の半分程度を削除して最終行にスクロールし直す、ということをやってます
・textbox.Selectで先頭から削除する容量まで選択
・textbox にDELキー送出
・最終行にカーソル移動
・textbox.ScrollCaretでスクロール
これでわりと違和感なく表示できてます
#他にいい方法があれば私も知りたいところです
投稿2019/03/08 08:38
総合スコア88180
0
http://www.woodensoldier.info/computer/csharptips/125.htm
textBox1.AppendText(message + "\r\n");
textBoxを使うなら、
AppendTextが最強なので、適当なタイミングで、消すをやればいいと思う。
TextのBindingでやると、遅い。全部のテキストを書き換えようとするからね。
差分書き換えみたいなことをできないといけない。
循環バッファ は、みたいな機構は、やりたいけど、専用のコントロールが必要そう。
投稿2019/03/08 10:53
総合スコア1986
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/03/11 01:54