Câu trả lời này mô tả một giải pháp sử dụng MVVM.
Giải pháp này rất tuyệt nếu bạn muốn thêm hộp ghi nhật ký vào cửa sổ, nó sẽ tự động cuộn xuống phía dưới mỗi lần thêm thông điệp ghi nhật ký mới.
Khi các thuộc tính đính kèm này được thêm vào, chúng có thể được sử dụng lại ở bất cứ đâu, do đó, nó tạo ra phần mềm rất mô-đun và có thể tái sử dụng.
Thêm XAML này:
<TextBox IsReadOnly="True"
Foreground="Gainsboro"
FontSize="13"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="True"
attachedBehaviors:TextBoxApppendBehaviors.AppendText="{Binding LogBoxViewModel.AttachedPropertyAppend}"
attachedBehaviors:TextBoxClearBehavior.TextBoxClear="{Binding LogBoxViewModel.AttachedPropertyClear}"
TextWrapping="Wrap">
Thêm tài sản đính kèm này:
public static class TextBoxApppendBehaviors
{
#region AppendText Attached Property
public static readonly DependencyProperty AppendTextProperty =
DependencyProperty.RegisterAttached(
"AppendText",
typeof (string),
typeof (TextBoxApppendBehaviors),
new UIPropertyMetadata(null, OnAppendTextChanged));
public static string GetAppendText(TextBox textBox)
{
return (string)textBox.GetValue(AppendTextProperty);
}
public static void SetAppendText(
TextBox textBox,
string value)
{
textBox.SetValue(AppendTextProperty, value);
}
private static void OnAppendTextChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs args)
{
if (args.NewValue == null)
{
return;
}
string toAppend = args.NewValue.ToString();
if (toAppend == "")
{
return;
}
TextBox textBox = d as TextBox;
textBox?.AppendText(toAppend);
textBox?.ScrollToEnd();
}
#endregion
}
Và tài sản đính kèm này (để xóa hộp):
public static class TextBoxClearBehavior
{
public static readonly DependencyProperty TextBoxClearProperty =
DependencyProperty.RegisterAttached(
"TextBoxClear",
typeof(bool),
typeof(TextBoxClearBehavior),
new UIPropertyMetadata(false, OnTextBoxClearPropertyChanged));
public static bool GetTextBoxClear(DependencyObject obj)
{
return (bool)obj.GetValue(TextBoxClearProperty);
}
public static void SetTextBoxClear(DependencyObject obj, bool value)
{
obj.SetValue(TextBoxClearProperty, value);
}
private static void OnTextBoxClearPropertyChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs args)
{
if ((bool)args.NewValue == false)
{
return;
}
var textBox = (TextBox)d;
textBox?.Clear();
}
}
Sau đó, nếu bạn đang sử dụng khung tiêm phụ thuộc như MEF, bạn có thể đặt tất cả mã cụ thể ghi nhật ký vào ViewModel của riêng nó:
public interface ILogBoxViewModel
{
void CmdAppend(string toAppend);
void CmdClear();
bool AttachedPropertyClear { get; set; }
string AttachedPropertyAppend { get; set; }
}
[Export(typeof(ILogBoxViewModel))]
public class LogBoxViewModel : ILogBoxViewModel, INotifyPropertyChanged
{
private readonly ILog _log = LogManager.GetLogger<LogBoxViewModel>();
private bool _attachedPropertyClear;
private string _attachedPropertyAppend;
public void CmdAppend(string toAppend)
{
string toLog = $"{DateTime.Now:HH:mm:ss} - {toAppend}\n";
// Attached properties only fire on a change. This means it will still work if we publish the same message twice.
AttachedPropertyAppend = "";
AttachedPropertyAppend = toLog;
_log.Info($"Appended to log box: {toAppend}.");
}
public void CmdClear()
{
AttachedPropertyClear = false;
AttachedPropertyClear = true;
_log.Info($"Cleared the GUI log box.");
}
public bool AttachedPropertyClear
{
get { return _attachedPropertyClear; }
set { _attachedPropertyClear = value; OnPropertyChanged(); }
}
public string AttachedPropertyAppend
{
get { return _attachedPropertyAppend; }
set { _attachedPropertyAppend = value; OnPropertyChanged(); }
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Đây là cách nó hoạt động:
- ViewModel bật tắt các Thuộc tính được đính kèm để điều khiển TextBox.
- Khi sử dụng "Nối", nó nhanh như chớp.
- Bất kỳ ViewModel nào khác cũng có thể tạo thông điệp ghi nhật ký bằng cách gọi các phương thức trên ViewModel đăng nhập.
- Khi chúng tôi sử dụng ScrollViewer được tích hợp trong TextBox, chúng tôi có thể làm cho nó tự động cuộn xuống dưới cùng của hộp văn bản mỗi khi một tin nhắn mới được thêm vào.
TextBlock
hai lần vàTextBox
một lần.