Основная проблема заключается в том, что, поскольку TextReader.Read()
является блокирующей операцией, вы не можете выполнить ее в потоке пользовательского интерфейса без блокировки пользовательского интерфейса.
Я бы начал с создания класса, который а) реализует INotifyPropertyChanged
и б) использует BackgroundWorker
, который читает из Console.In
. Если вам требуется посимвольный ввод, метод будет использовать Read()
. Каждый символ, который он читает, должен быть добавлен к свойству string
, а затем метод должен вызвать BackgroundWorker.ReportProgress
.
ReportProgress
повышает ProgressChanged
в потоке, в котором был создан BackgroundWorker
(в отличие от потока, которым управляет BackgroundWorker
). Если этот обработчик события вызывает PropertyChanged
в потоке пользовательского интерфейса, то любые привязки, использующие этот объект, будут обновлены.
Конечный результат выглядит примерно так:
public class Listener : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private BackgroundWorker _BW;
public Listener()
{
_BW = new BackgroundWorker();
_BW.WorkerReportsProgress = true;
_BW.ProgressChanged += BW_ProgressChanged;
_BW.DoWork += BW_DoWork;
_BW.RunWorkerAsync();
Input = string.Empty;
}
private void BW_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
int ch = Console.In.Read();
if (ch != -1)
{
Input += Convert.ToChar(ch);
_BW.ReportProgress(0);
}
}
}
private void BW_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
PropertyChangedEventHandler h = PropertyChanged;
if (h != null)
{
h(this, new PropertyChangedEventArgs("Input"));
}
}
public string Input { get; private set; }
}
... а в XAML вы используете его так:
<TextBlock Text="{Binding Input}">
<TextBlock.DataContext>
<local:Listener />
</TextBlock.DataContext>
</TextBlock>
Отказ от ответственности: я написал все это на макушке, и это, кажется, работает, но я уверен, что в нем есть ошибки. Реальная реализация этого будет использовать StringBuilder
, а не просто конкатенацию символов в конце Input
. Кроме того, нет способа закрыть это; поток просто умирает, когда программа завершается. Это, вероятно, нежелательное поведение.