Good day! In my ListView.ItemTemplate, I have a RichTextBox with a zabindenny Document. Virtualization is included in the ListView, but by scrolling through this element, memory consumption increases and increases. I tried to bind the same thing to TextBlock and with memory everything was ok. But, unfortunately, TextBlock does not fit, because does not support selection. And TextBox is also not suitable, because along with the text to display images. help me please

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|[az]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:/(?:[-\w~!$+|.,=]|%[af\d]{2})+)+|/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!$+|.,*:]|%[af\d{2}])+=(?:[-\w~!$+|.,*:=]|%[af\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[af\d{2}])+=(?:[-\w~!$+|.,*:=]|%[af\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!$+|.,*:=]|%[af\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(); } } 

UPDATED VIEW:

  <CollectionViewSource x:Key="ItemListViewSource" IsLiveSortingRequested="True" Source="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=Tag.Messages}"> <CollectionViewSource.SortDescriptions> <scm:SortDescription PropertyName="date" /> </CollectionViewSource.SortDescriptions> </CollectionViewSource> <Style x:Key="lvItemStyle" TargetType="{x:Type ListViewItem}"> <Setter Property="Background" Value="White" /> <Setter Property="Padding" Value="0" /> <Setter Property="Focusable" Value="False" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListViewItem}"> <Border x:Name="Bd" Background="{TemplateBinding Background}" BorderThickness="0" Padding="{TemplateBinding Padding}"> <ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" /> </Border> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <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="SelectionMode" Value="Multiple" /> <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> <DataTemplate x:Key="MessageTemplate"> <Grid Margin="0,7,0,7"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Image Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" Width="40" Height="40" Margin="5,0,10,0" VerticalAlignment="Top" Source="{Binding Converter={StaticResource getAvatarForChat}, Path=fromId, Mode=OneWay, ConverterParameter=40}"> <Image.Clip> <EllipseGeometry Center="20,20" RadiusX="20" RadiusY="20" /> </Image.Clip> </Image> <TextBlock Grid.Row="0" Grid.Column="1" Margin="0" VerticalAlignment="Top" FontSize="13" FontWeight="SemiBold" Padding="0" Text="{Binding chatTitle, Mode=OneWay" /> <TextBlock Grid.Row="0" Grid.Column="2" Margin="10,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="13" FontWeight="ExtraLight" Padding="0" Text="{Binding Path=date, Converter={StaticResource dateConverter}, ConverterParameter=HH:mm, Mode=OneWay}" /> <FlowDocumentScrollViewer Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,3,0,0" Document="{Binding message, Converter={StaticResource documentConverter}, Mode=OneWay}" Padding="0"/> </Grid> </DataTemplate> <ListView x:Name="listView" Grid.Row="0" ItemsSource="{Binding Source={StaticResource ItemListViewSource}, NotifyOnTargetUpdated=True}"" ItemTemplate="StaticResource MessageTemplate" Style="{StaticResource lvStyle}"> </ListView> 
  • It would be nice to see the code, and even better MCVE - Ev_Hyper
  • Excellent ... I can not understand, you have that RichTextBox read-only use? - Ev_Hyper
  • @Ev_Hyper, that's right, I need an element that would support selection, text output, and images, and hyperlinks, the other I could not find - Anton Man'kov
  • Then it is much easier to use regular FlowDocument - Ev_Hyper
  • Unfortunately, this problem did not completely solve, but the memory consumption decreased a bit, thanks - Anton Man'kov

0