如何使用 xaml 将内容动态添加到 wpf 应用程序中的富文本框
how to dynamically add content to a rich text box in a wpf application using xaml
我正在开发一个 GUI,用户可以在其中连接到服务器并读取数据。数据需要显示在 GUI 上。为此,我使用 TabControl,其 ContentTemplate 设置为 RichTextBox。 XAML代码如下
<TabControl x:Name="tabControl1" HorizontalAlignment="Stretch" MinHeight="50" Margin="0,0,0,0.2" Width="884"
ItemsSource="{Binding Titles, Mode=TwoWay}" Height="454" VerticalAlignment="Bottom">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<RichTextBox Margin="10" VerticalScrollBarVisibility="Visible" >
<FlowDocument>
<Paragraph FontSize="12" FontFamily="Courier New">
<Run Text="{Binding Content}"></Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
添加新标签并设置其header/content(静态)的后台代码如下
public class MainWindowVM : INotifyPropertyChanged
{
public MainWindowVM()
{
Titles = new ObservableCollection<Item>();
}
public class Item
{
public string Header { get; set; }
public string Content { get; set; }
}
public ObservableCollection<Item> Titles
{
get { return _titles; }
set
{
_titles = value;
OnPropertyChanged("Titles");
}
}
static int tabs = 1;
private ObservableCollection<Item> _titles;
private ICommand _addTab;
private ICommand _removeTab;
public ICommand AddTab
{
get
{
_addTab = new TabRelayCommand(
x =>
{
AddTabItem();
});
return _addTab;
}
}
public ICommand RemoveTab
{
get
{
_removeTab = new TabRelayCommand(
x =>
{
RemoveTabItem();
});
return _removeTab;
}
}
private void RemoveTabItem()
{
if (Titles.Count > 0)
{
Titles.Remove(Titles.Last());
tabs--;
}
}
public Item AddTabItem()
{
var header = "Log_" + tabs;
var content = "Content " + tabs;
var item = new Item { Header = header, Content = content };
Titles.Add(item);
tabs++;
OnPropertyChanged("Titles");
return item;
}
public void AddTabItem(string strFileName, string strContent)
{
var header = strFileName;
var content = strContent;
var item = new Item { Header = header, Content = content };
Titles.Add(item);
tabs++;
OnPropertyChanged("Titles");
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
不过我需要动态设置header的内容(从socket读取的数据)。我可以读取字符串格式的数据。
请建议我如何通过附加字符串来设置 RichTextBox 的内容。
我是 C# 的新手。提前致谢
编辑:
按钮单击事件后,我的应用程序连接到服务器。我还启动了一个从套接字读取数据的并行任务。
面临的问题: 花费了太多 CPU 时间(我可以在任务管理器中的进程下看到最多 80) .
private void BtnConnect_Click(object sender, RoutedEventArgs e)
{
//connect
TCPClientClass tcpClient = TCPConnHandler.ConnectToService(tbIPAddress.Text);
if (tcpClient != null)
{
MessageBox.Show("Connected to " + tbIPAddress.Text);
//open new tab
var item = MainWindowVMObj.AddTabItem();
//now run a task to display the data in the tab
Thread thTabControl = new Thread(() =>
{
while (tcpClient.Connected)
{
String str = tcpClient.GetDataFromServer();
if (!String.IsNullOrEmpty(str))
tabControl1.Dispatcher.BeginInvoke((Action)(() => item.Content += str));
Thread.Sleep(200);
}
//item.Dispatcher.BeginInvoke
});
thTabControl.Start();
}
}
您可以在 Titles
中查找要更新的 Item
并设置其 Content
属性。
例如,这会设置 ObservableCollection<Item>
中第一项(索引 0)的 属性:
Titles[0].Content += "append...";
Item
class 也应该实现 INotifyPropertyChanged
以便您在不切换标签的情况下看到更改:
public class Item : INotifyPropertyChanged
{
public string Header { get; set; }
private string _content;
public string Content
{
get { return _content; }
set { _content = value; OnPropertyChanged(nameof(Content)); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
我正在开发一个 GUI,用户可以在其中连接到服务器并读取数据。数据需要显示在 GUI 上。为此,我使用 TabControl,其 ContentTemplate 设置为 RichTextBox。 XAML代码如下
<TabControl x:Name="tabControl1" HorizontalAlignment="Stretch" MinHeight="50" Margin="0,0,0,0.2" Width="884"
ItemsSource="{Binding Titles, Mode=TwoWay}" Height="454" VerticalAlignment="Bottom">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<RichTextBox Margin="10" VerticalScrollBarVisibility="Visible" >
<FlowDocument>
<Paragraph FontSize="12" FontFamily="Courier New">
<Run Text="{Binding Content}"></Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
添加新标签并设置其header/content(静态)的后台代码如下
public class MainWindowVM : INotifyPropertyChanged
{
public MainWindowVM()
{
Titles = new ObservableCollection<Item>();
}
public class Item
{
public string Header { get; set; }
public string Content { get; set; }
}
public ObservableCollection<Item> Titles
{
get { return _titles; }
set
{
_titles = value;
OnPropertyChanged("Titles");
}
}
static int tabs = 1;
private ObservableCollection<Item> _titles;
private ICommand _addTab;
private ICommand _removeTab;
public ICommand AddTab
{
get
{
_addTab = new TabRelayCommand(
x =>
{
AddTabItem();
});
return _addTab;
}
}
public ICommand RemoveTab
{
get
{
_removeTab = new TabRelayCommand(
x =>
{
RemoveTabItem();
});
return _removeTab;
}
}
private void RemoveTabItem()
{
if (Titles.Count > 0)
{
Titles.Remove(Titles.Last());
tabs--;
}
}
public Item AddTabItem()
{
var header = "Log_" + tabs;
var content = "Content " + tabs;
var item = new Item { Header = header, Content = content };
Titles.Add(item);
tabs++;
OnPropertyChanged("Titles");
return item;
}
public void AddTabItem(string strFileName, string strContent)
{
var header = strFileName;
var content = strContent;
var item = new Item { Header = header, Content = content };
Titles.Add(item);
tabs++;
OnPropertyChanged("Titles");
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
不过我需要动态设置header的内容(从socket读取的数据)。我可以读取字符串格式的数据。 请建议我如何通过附加字符串来设置 RichTextBox 的内容。 我是 C# 的新手。提前致谢
编辑: 按钮单击事件后,我的应用程序连接到服务器。我还启动了一个从套接字读取数据的并行任务。
面临的问题: 花费了太多 CPU 时间(我可以在任务管理器中的进程下看到最多 80) .
private void BtnConnect_Click(object sender, RoutedEventArgs e)
{
//connect
TCPClientClass tcpClient = TCPConnHandler.ConnectToService(tbIPAddress.Text);
if (tcpClient != null)
{
MessageBox.Show("Connected to " + tbIPAddress.Text);
//open new tab
var item = MainWindowVMObj.AddTabItem();
//now run a task to display the data in the tab
Thread thTabControl = new Thread(() =>
{
while (tcpClient.Connected)
{
String str = tcpClient.GetDataFromServer();
if (!String.IsNullOrEmpty(str))
tabControl1.Dispatcher.BeginInvoke((Action)(() => item.Content += str));
Thread.Sleep(200);
}
//item.Dispatcher.BeginInvoke
});
thTabControl.Start();
}
}
您可以在 Titles
中查找要更新的 Item
并设置其 Content
属性。
例如,这会设置 ObservableCollection<Item>
中第一项(索引 0)的 属性:
Titles[0].Content += "append...";
Item
class 也应该实现 INotifyPropertyChanged
以便您在不切换标签的情况下看到更改:
public class Item : INotifyPropertyChanged
{
public string Header { get; set; }
private string _content;
public string Content
{
get { return _content; }
set { _content = value; OnPropertyChanged(nameof(Content)); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}