我是WPF的新手,我发现了一些类似的问题,但不能完全弄清楚最后一部分。我有一个带有ObservableCollection的ViewModel,其中包含错误消息。我想在表单上显示这些并允许用户选择和复制全部或部分消息。 (在WinForm应用程序的过去,我使用了RichTextBox,但我无法弄清楚如何将其绑定到WPF中的集合。)
我使用下面的xaml得到了我的样子,但是没有内置的方法可以像RichTextBox一样选择和复制。有谁知道我应该使用哪个控件,或者是否有方法可以选择/复制所有TextBlocks的内容,或者将它绑定到RichTextBox?
<Grid Margin="6">
<ScrollViewer VerticalScrollBarVisibility="Auto" Height="40" Grid.Column="0" Margin="6">
<ItemsControl ItemsSource="{Binding ErrorMessages}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Mode=OneWay}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
[编辑] @Andrey Shvydky - 这不符合评论。 我花了一段时间来弄清楚正确的语法(特别是/,这个东西),但最终我得到了如下所示的Flow Document语法。它在表单上看起来是正确的,起初似乎支持select all / copy。但是当我在选择全部/副本之后粘贴时,没有任何东西出现。谁知道为什么?
<Grid Margin="6">
<FlowDocumentScrollViewer>
<FlowDocument >
<Paragraph>
<ItemsControl ItemsSource="{Binding ErrorMessages, Mode=OneWay}" />
<Run Text="{Binding /, Mode=OneWay}" />
</Paragraph>
</FlowDocument>
</FlowDocumentScrollViewer>
</Grid>
答案 0 :(得分:1)
可能有助于生成FlowDocument并在FlowDocumentReader中显示此文档。 尝试从这篇文章开始:Flow Document Overview。
生成示例:
void ShowErrors(FlowDocumentReader reader, Exception[] errors) {
FlowDocument doc = new FlowDocument();
foreach (var e in errors) {
doc.Blocks.Add(new Paragraph(new Run(e.GetType().Name)) {
Style = (Style)this.FindResource("header")
});
doc.Blocks.Add(new Paragraph(new Run(e.Message)) {
Style = (Style)this.FindResource("text")
});
}
reader.Document = doc;
}
在这个例子中,我在flowdocument中添加了一些文本样式。看看XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="header" TargetType="{x:Type Paragraph}">
<Setter Property="FontWeight" Value="Bold"/>
</Style>
<Style x:Key="text" TargetType="{x:Type Paragraph}">
<Setter Property="Margin" Value="30, 0, 0, 0"/>
</Style>
</Window.Resources>
<FlowDocumentReader Name="reader">
</FlowDocumentReader>
结果:
答案 1 :(得分:1)
最简单的方法:
假设您的viewmodel实现了INotifyPropertyChange,请为ObservableCollection PropertyChanged事件创建一个事件处理程序。创建一个属性,该属性将可观察集合中的所有项聚合为单个字符串。每当可观察集合发生变化时,都会触发新属性的通知事件。绑定到该属性
public class ViewModel : INotifyPropertyChange
{
public ViewModel()
{
MyStrings.CollectionChanged += ChangedCollection;
}
public ObservableCollection<string> MyStrings{get;set;}
public void ChangedCollection(args,args)
{
base.PropertyChanged("MyAllerts");
}
public string MyAllerts
{
get
{
string collated = "";
foreach(var allert in MyStrings)
{
collated += allert;
collated += "\n";
}
}
}
}
我知道这段代码充满了错误(我用SO而不是VS写的),但它应该给你一些想法。
答案 2 :(得分:1)
除非你有大量的信息,否则简单的converter可能是可行的:
<TextBox IsReadOnly="True">
<TextBox.Text>
<Binding Path="Messages" Mode="OneWay">
<Binding.Converter>
<vc:JoinStringsConverter />
</Binding.Converter>
</Binding>
</TextBox.Text>
</TextBox>
public class JoinStringsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var strings = value as IEnumerable<string>;
return string.Join(Environment.NewLine, strings);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
答案 3 :(得分:0)
<Grid Margin="6">
<ScrollViewer VerticalScrollBarVisibility="Auto" Height="40" Grid.Column="0" Margin="6">
<ItemsControl ItemsSource="{Binding ErrorMessages}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding ViewModelMemberRepresentingYourErrorMessage}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>