RichTextBox как DataTemplate в ListView

379
06 января 2017, 08:28

Доброго времени суток! У меня в качестве ListView.ItemTemplate является RichTextBox с забинденным Document'ом. В ListView включена виртуализация, но, прокручивая данный элемент, потребление памяти увеличивается и увеличивается. Пробовал забиндить то же самое на TextBlock и с памятью все было ок. Но, к сожалению, TextBlock не подходит, т.к. не поддерживает выделение. И TextBox тоже не подходит, т.к. вместе с текстом необходимо выводить изображения. Помогите пожалуйста

VIEW:

<Style x:Key="richBox" TargetType="{x:Type RichTextBox}">
    <Setter Property="IsReadOnly" Value="True" />
    <Setter Property="IsDocumentEnabled" Value="True" />
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="Foreground" Value="#11294f" />
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="FontSize" Value="13" />
</Style>
<DataTemplate x:Key="ListViewItemTemplate">
    <richBox:BindableRichTextBox Margin="0"
                             AutoWordSelection="True"
                             UndoLimit="0"
                             Document="{Binding message,
                                                Converter={StaticResource documentConverter},
                                                Mode=OneWay}"
                             Padding="0"
                             Style="{StaticResource richBox}">
    <richBox:BindableRichTextBox.Resources>
        <Style TargetType="{x:Type Paragraph}">
            <Setter Property="Margin" Value="0" />
        </Style>
    </richBox:BindableRichTextBox.Resources>
</richBox:BindableRichTextBox>
</DataTemplate>
<Style x:Key="lvItemStyle" TargetType="{x:Type ListViewItem}">
    <Setter Property="Background" Value="White" />
    <Setter Property="Padding" Value="0" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListViewItem}">
                <Border x:Name="Bd"
                        Margin="5"
                        Background="{TemplateBinding Background}"
                        BorderThickness="0"
                        Padding="{TemplateBinding Padding}">
                    <ContentPresenter HorizontalAlignment="Left" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="true">
            <Setter Property="Background" Value="White" />
        </Trigger>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="Background" Value="LightGray" />
        </Trigger>
    </Style.Triggers>
</Style>
<Style x:Key="lvStyle" TargetType="{x:Type ListView}">
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="Background" Value="White" />
    <Setter Property="ScrollViewer.CanContentScroll" Value="True" />
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
    <Setter Property="VirtualizingPanel.IsVirtualizing" Value="True" />
    <Setter Property="VirtualizingPanel.ScrollUnit" Value="Pixel" />
    <Setter Property="Margin" Value="0" />
    <Setter Property="ItemContainerStyle" Value="{StaticResource lvItemStyle}" />
    <Setter Property="Padding" Value="0" />
</Style>
<ListView Grid.Row="0"
          Focusable="False"
          ItemsSource="{Binding Source={StaticResource ItemListViewSource},
                                NotifyOnTargetUpdated=True}"
          KeyboardNavigation.IsTabStop="False"
          KeyboardNavigation.TabNavigation="None" 
          ItemTemplate="{StaticResource ListViewItemTemplate}"
          Style="{StaticResource lvStyle}" />

BindableRichTextBox:

public class BindableRichTextBox : RichTextBox
{
    public BindableRichTextBox()
    {
         var commandBindings = new CommandBinding(ApplicationCommands.Copy);
        commandBindings.Executed += (sender, args) =>
        {
            var rtb = sender as RichTextBox;
            if (rtb == null)
            {
                args.Handled = true;
                return;
            }
            Clipboard.SetText(rtb.Selection.TextSelectionToString());
            args.Handled = true;
        };
        this.CommandBindings.Add(commandBindings);
    }
    public static readonly DependencyProperty DocumentProperty = DependencyProperty.Register("Document", typeof(FlowDocument),
        typeof(BindableRichTextBox), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnDocumentChanged)));
    public new FlowDocument Document
    {
        get
        {
            return (FlowDocument)this.GetValue(DocumentProperty);
        }
        set
        {
            this.SetValue(DocumentProperty, value);
        }
    }
    public static void OnDocumentChanged(DependencyObject obj,
        DependencyPropertyChangedEventArgs args)
    {
        try
        {
            var rtb = (RichTextBox)obj;
            rtb.Document = (FlowDocument)args.NewValue ?? new FlowDocument();
        }
        catch { }
    }
}

Converter:

public class DocumentConverter : IValueConverter
{
    private static readonly Regex RE_URL = new Regex(@"(?#Protocol)(?:(?:ht|f)tp(?:s?)\:\/\/|~/|/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)?");
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        try
        {
            var doc = new FlowDocument();
            var s = value as string;
            if (s != null)
            {
                var paragraph = new Paragraph();
                var last_pos = 0;
                foreach (Match match in RE_URL.Matches(s))
                {
                    if (match.Index != last_pos)
                    {
                        var raw_text = s.Substring(last_pos, match.Index - last_pos);
                        paragraph.Inlines.AddRange(EmojiHelper.DisplayEmoji(raw_text));
                    }
                    try
                    {
                        var link = new Hyperlink(new Run(match.Value))
                        {
                            NavigateUri = new Uri(match.Value)
                        };
                        link.Click += OnUrlClick;
                        paragraph.Inlines.Add(link);
                    }
                    catch { }
                    last_pos = match.Index + match.Length;
                }
                if (last_pos < s.Length)
                    paragraph.Inlines.AddRange(EmojiHelper.DisplayEmoji(s.Substring(last_pos)));
                doc.Blocks.Add(paragraph);
            }
            return doc;
        }
        catch { return null; }
    }
    private static void OnUrlClick(object sender, RoutedEventArgs e)
    {
        try
        {
            var link = (Hyperlink)sender;
            Process.Start(link.NavigateUri.ToString());
        }
        catch { }
    }
    public object ConvertBack(object value, Type targetTypes, object parameter,
        System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}
READ ALSO
Не правильная дозапись в бинарный файл C#

Не правильная дозапись в бинарный файл C#

Всем доброго времени сутокПомогите разобраться, написал приложение которое производит дозапись бинарного файла, но дозапись только в 101 значение,...

393
Делегаты C#. Invoke

Делегаты C#. Invoke

В качестве примера возьмем следующий код и опустим все подробности

437
FarseerPhysics MonoGame

FarseerPhysics MonoGame

Всем приветНачал писать игру и пришел момент когда надо перемещаться персонажем

366
Фильтрация данных в DataGridView с помощью LINQ

Фильтрация данных в DataGridView с помощью LINQ

Есть пустой DataGridViewкоторый привязан к источнику данных, и настроен на отображения двух столбцов Id и Name

833