如何在UserControl中显示ObservableCollection <string> </string>

时间:2011-06-14 05:15:45

标签: wpf richtextbox observablecollection copy-paste textblock

我是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>

4 个答案:

答案 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>

结果:

enter image description here

答案 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>