Как отобразить ObservableCollection <string>в пользовательском контроле - PullRequest
1 голос
/ 14 июня 2011

Я новичок в WPF, и я нашел несколько похожих вопросов, но не могу понять последнюю часть.У меня есть ViewModel с ObservableCollection, которая содержит сообщения об ошибках.Я хочу отобразить их в форме И позволить пользователю выбрать и скопировать все или часть сообщений.(Раньше в приложениях WinForm для этого я использовал RichTextBox, но я не могу понять, как привязать его к коллекции в WPF.)

Я получил такой вид, как следующий, с помощью следующего xaml, но нет встроенного способа выбора и копирования, как я мог бы с RichTextBox.Кто-нибудь знает, какой элемент управления мне следует использовать, или есть ли способ включить / скопировать содержимое всех текстовых блоков или способ связать это с 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>

[Редактировать] @ Андрей Швыдкий- Это не вписывается в комментарий.Мне потребовалось некоторое время, чтобы выяснить правильный синтаксис (особенно /, вещь), но в итоге я получил синтаксис Flow Document, показанный ниже.Это выглядит правильно в форме и на первый взгляд, кажется, поддерживает выбрать все / копия.Но когда я вставляю после выбора все / копия, ничего не появляется.Кто-нибудь знает почему?

 <Grid Margin="6">
    <FlowDocumentScrollViewer>
        <FlowDocument >
            <Paragraph>
                <ItemsControl ItemsSource="{Binding ErrorMessages, Mode=OneWay}" />
                <Run Text="{Binding /, Mode=OneWay}" />
            </Paragraph>
        </FlowDocument>
    </FlowDocumentScrollViewer>
</Grid>

Ответы [ 4 ]

1 голос
/ 14 июня 2011

Если у вас нет большого количества сообщений, может пригодиться простой конвертер :

<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();
    }
}
1 голос
/ 14 июня 2011

Может быть полезно для создания FlowDocument и отображения этого документа в FlowDocumentReader .Попробуйте начать с этой статьи: Обзор потокового документа .

Пример создания:

    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;
    }

В этом примере я добавил несколько стилей для текста в потоковом документе.Пожалуйста, посмотрите на 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 голос
/ 14 июня 2011

Самый простой способ:

Предполагая, что ваша модель представления реализует 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), но он должен дать вам некоторое представление.

0 голосов
/ 14 июня 2011
<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>
...