2

I have a UserControl which is a list of items wherein each item contains a lot of TextBox and TextBlock controls. I tried disabling undo steps but the memory consumption is quite high even after adding 10 items in the list. I tried running the memory analysis tool and I could see that TextBoxes are the biggest consumer of memory of around 50 MB.

My XAML is as below

<UserControl.Resources>
    <converter:GenericButtonConverter x:Key="ButtonConverter"/>
    <DataTemplate x:Key="RawSendListTemplate">
        <ListBoxItem BorderBrush="LightGray" BorderThickness="0.5" HorizontalAlignment="Stretch" Margin="3,1,3,1">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="52"/>
                    <ColumnDefinition Width="80"/>
                    <ColumnDefinition Width="70"/>
                    <ColumnDefinition Width="40"/>
                    <ColumnDefinition Width="40"/>
                    <ColumnDefinition Width="40"/>
                    <ColumnDefinition Width="80"/>
                    <ColumnDefinition Width="60"/>
                    <ColumnDefinition Width="40"/>
                    <ColumnDefinition Width="60"/>
                    <ColumnDefinition Width="45"/>
                    <ColumnDefinition Width="36"/>
                    <ColumnDefinition Width="36"/>
                    <ColumnDefinition Width="36"/>
                    <ColumnDefinition Width="36"/>
                    <ColumnDefinition Width="36"/>
                    <ColumnDefinition Width="36"/>
                    <ColumnDefinition Width="36"/>
                    <ColumnDefinition Width="36"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock  Grid.Column="0"  Text="ID" MinWidth="20" FontSize="11" FontWeight="Bold" Foreground="Coral" 
                            VerticalAlignment="Center" TextAlignment="Center" Margin="0,0,5,0" />
                <TextBox    Grid.Column="1"  Text="{Binding Path=CanId, UpdateSourceTrigger=PropertyChanged}" MinWidth="20" FontSize="11"   Foreground="Blue" FontWeight="SemiBold" TextWrapping="NoWrap" MaxLength="8"
                            VerticalAlignment="Center" HorizontalContentAlignment="Center" Margin="0,0,15,0" UndoLimit="0" AcceptsReturn="False"  IsUndoEnabled="False" MaxLines="1" />

                <TextBlock  Grid.Column="2"  Text="CHANNEL" MinWidth="20" FontSize="11"  FontWeight="Bold" Foreground="Coral" 
                            VerticalAlignment="Center" TextAlignment="Center" Margin="0,0,5,0" />
                <TextBox    Grid.Column="3"  Text="{Binding Path=Channel, UpdateSourceTrigger=PropertyChanged}" MinWidth="20" FontSize="11"  Foreground="Blue" FontWeight="SemiBold" TextWrapping="NoWrap" MaxLength="1"
                            VerticalAlignment="Center" HorizontalContentAlignment="Center" Margin="0,0,15,0" UndoLimit="0" AcceptsReturn="False"  IsUndoEnabled="False" MaxLines="1"/>

                <TextBlock  Grid.Column="4"  Text="Length" MinWidth="20" FontSize="11"  FontWeight="Bold" Foreground="Coral" 
                            VerticalAlignment="Center" TextAlignment="Center" Margin="0,0,5,0" />
                <TextBox    Grid.Column="5"  Text="{Binding Path=Len , UpdateSourceTrigger=PropertyChanged}" MinWidth="20" FontSize="11"  Foreground="Blue" FontWeight="SemiBold"  MaxLength="1"
                            VerticalAlignment="Center" HorizontalContentAlignment="Center" Margin="0,0,15,0" UndoLimit="0" AcceptsReturn="False"  IsUndoEnabled="False" MaxLines="1"/>

                <Button     Grid.Column="6"  Content="Send" x:Name="RawSendButton" IsEnabled="{Binding Path=SendButtonEnabled}" MinWidth="20" FontSize="11"  FontWeight="SemiBold" Foreground="Black"
                            VerticalAlignment="Center" HorizontalContentAlignment="Center" Margin="0,0,5,0"
                            Command="{Binding ButtonClick}" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Name, Converter={StaticResource ButtonConverter}}"/>

                <TextBlock  Grid.Column="7"  Text="CYCLE" MinWidth="20" FontSize="11" FontWeight="Bold" Foreground="Coral" 
                            VerticalAlignment="Center" TextAlignment="Center" Margin="0,0,5,0" />
                <TextBox    Grid.Column="8"  Text="{Binding Path=CycleTimeMs, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding Path=SendButtonEnabled}" MinWidth="20" FontSize="11"  Foreground="Blue" FontWeight="SemiBold" MaxLength="4"
                            VerticalAlignment="Center" TextAlignment="Center" HorizontalContentAlignment="Center" Margin="0,0,5,0" UndoLimit="0" AcceptsReturn="False"  IsUndoEnabled="False" MaxLines="1"/>
                <CheckBox   Grid.Column="9"  IsChecked="{Binding Path=CyclicEnableChecked, Mode=TwoWay}" IsEnabled="{Binding Path=CyclicEnable, UpdateSourceTrigger=PropertyChanged}"    MinWidth="20" 
                            VerticalAlignment="Center" HorizontalContentAlignment="Center" Margin="0,0,40,0"/>

                <TextBlock  Grid.Column="10" Text="DATA" MinWidth="20" FontSize="11" FontWeight="Bold" Foreground="Coral" 
                            VerticalAlignment="Center" TextAlignment="Left"  Margin="0,0,10,0" />
                <TextBox    Grid.Column="11" Text="{Binding Path=Byte1}"  IsEnabled="{Binding Path=Byte1Enabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="20" FontSize="11" Foreground="Blue" FontWeight="SemiBold" MaxLength="2"
                            TextAlignment="Right"  VerticalAlignment="Center" HorizontalContentAlignment="Center" Margin="0,0,5,0" UndoLimit="0" AcceptsReturn="False"  IsUndoEnabled="False" MaxLines="1"/>
                <TextBox    Grid.Column="12" Text="{Binding Path=Byte2}"  IsEnabled="{Binding Path=Byte2Enabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="20" FontSize="11" Foreground="Blue" FontWeight="SemiBold" MaxLength="2"
                            VerticalAlignment="Center" TextAlignment="Right" HorizontalContentAlignment="Center" Margin="0,0,5,0" UndoLimit="0" AcceptsReturn="False"  IsUndoEnabled="False" MaxLines="1"/>
                <TextBox    Grid.Column="13" Text="{Binding Path=Byte3}"  IsEnabled="{Binding Path=Byte3Enabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="20" FontSize="11" Foreground="Blue" FontWeight="SemiBold" MaxLength="2"
                            VerticalAlignment="Center" TextAlignment="Right" HorizontalContentAlignment="Center" Margin="0,0,5,0" UndoLimit="0" AcceptsReturn="False"  IsUndoEnabled="False" MaxLines="1"/>
                <TextBox    Grid.Column="14" Text="{Binding Path=Byte4}"  IsEnabled="{Binding Path=Byte4Enabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="20" FontSize="11" Foreground="Blue" FontWeight="SemiBold" MaxLength="2"
                            VerticalAlignment="Center" TextAlignment="Right" HorizontalContentAlignment="Center" Margin="0,0,5,0" UndoLimit="0" AcceptsReturn="False"  IsUndoEnabled="False" MaxLines="1"/>
                <TextBox    Grid.Column="15" Text="{Binding Path=Byte5}"  IsEnabled="{Binding Path=Byte5Enabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="20" FontSize="11" Foreground="Blue" FontWeight="SemiBold" MaxLength="2"
                            VerticalAlignment="Center" TextAlignment="Right" HorizontalContentAlignment="Center" Margin="0,0,5,0" UndoLimit="0" AcceptsReturn="False"  IsUndoEnabled="False" MaxLines="1"/>
                <TextBox    Grid.Column="16" Text="{Binding Path=Byte6}"  IsEnabled="{Binding Path=Byte6Enabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="20" FontSize="11" Foreground="Blue" FontWeight="SemiBold" MaxLength="2"
                            VerticalAlignment="Center" TextAlignment="Right" HorizontalContentAlignment="Center" Margin="0,0,5,0" UndoLimit="0" AcceptsReturn="False"  IsUndoEnabled="False" MaxLines="1"/>
                <TextBox    Grid.Column="17" Text="{Binding Path=Byte7}"  IsEnabled="{Binding Path=Byte7Enabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="20" FontSize="11" Foreground="Blue" FontWeight="SemiBold" MaxLength="2"
                            VerticalAlignment="Center" TextAlignment="Right" HorizontalContentAlignment="Center" Margin="0,0,5,0" UndoLimit="0" AcceptsReturn="False"  IsUndoEnabled="False" MaxLines="1"/>
                <TextBox    Grid.Column="18" Text="{Binding Path=Byte8}"  IsEnabled="{Binding Path=Byte8Enabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="20" FontSize="11" Foreground="Blue" FontWeight="SemiBold" MaxLength="2"
                            VerticalAlignment="Center" TextAlignment="Right" HorizontalContentAlignment="Center" Margin="0,0,5,0" UndoLimit="0" AcceptsReturn="False"  IsUndoEnabled="False" MaxLines="1"/>
            </Grid>
        </ListBoxItem>
    </DataTemplate>
</UserControl.Resources>        
<Grid>
    <ListBox x:Name="RawSendList" BorderThickness="1" BorderBrush="DarkGray" Margin="1" ItemsSource="{Binding MyViewModel.RawMessages}" ItemTemplate="{StaticResource RawSendListTemplate}" 
                SelectedItem="{Binding MyViewModel.SelectedRawMessageItem, Mode=OneWayToSource}" SelectionMode="Single" Background="OldLace"/>
</Grid>

I need some help reducing the memory footprint of the list item.

Function Name Total CPU (%) Self CPU (%) Total CPU (ms) Self CPU (ms) Module

  • Gazelle.exe (PID: 8516) 100.00 % 0.00 % 29761 0 Gazelle.exe

  • [External Code] 99.80 % 23.01 % 29701 6849 50 modules

  • Gazelle.App::Main 0.19 % 0.00 % 58 0 Gazelle.exe

  • Gazelle.MainWindow::InitializeComponent 0.01 % 0.00 % 2 0 Gazelle.exe

Object Type Count Size (Bytes) Inclusive Size (Bytes) Module

  • ListItem 10,464 251,136 573,839,736 PresentationCore.dll

  • TextBox 10,008 18,376,324 278,265,656 PresentationFramework.dll

  • List 25,098 23,258,200 185,202,668 mscorlib.dll

  • TextEditor 10,008 2,175,548 158,375,060 PresentationFramework.dll

  • Grid 12,624 12,400,172 151,944,940 PresentationFramework.dll

  • ListBoxItem 1,668 1,013,444 128,034,940 PresentationFramework.dll

  • TemplateNameScope 25,098 803,136 121,480,864 PresentationFramework.dll

  • ScrollViewer 10,015 10,694,204 81,834,452 PresentationFramework.dll

  • ContentPresenter 3,387 2,420,780 28,512,660 PresentationFramework.dll

  • EventHandler 233,861 10,732,196 25,202,352 mscorlib.dll

  • BindingExpression 65,292 24,139,292 24,189,152 PresentationFramework.dll

  • Border 13,419 11,634,248 18,898,436 PresentationFramework.dll

  • TextBoxView 10,008 11,549,424 18,597,828 PresentationFramework.dll

  • HybridDictionary 52,843 7,811,596 18,090,272 System.dll

  • ModifiedValue 192,048 4,803,732 16,476,568 WindowsBase.dll

  • ScrollBar 20,022 15,381,092 16,358,688 PresentationFramework.dll

  • ScrollContentPresenter 10,011 10,158,248 14,169,188 PresentationFramework.dll

[UPDATE]

Adding this in the XAML is making the Application more responsive

UndoLimit="0" AcceptsReturn="False"  IsUndoEnabled="False"

Now I am wondering where else I could gain some more

WinterS
  • 127
  • 11
  • 10
    Why? Memory is cheap. Are you getting OOM exceptions? If not, don't worry about it. Allocation is expensive, so the CLR tends to hold onto any memory allocated. Put down Task Manager and walk away. –  Sep 19 '14 at 20:13
  • What kind of memory did you measure? – Thomas Weller Sep 19 '14 at 20:16
  • After adding several items, the Application responsiveness is very slow. – WinterS Sep 19 '14 at 20:17
  • 1
    @WinterS Then you have something else that affects the system performance. – B.K. Sep 19 '14 at 20:20
  • I measured with Performance and Diagnostics, CPU usage is low, 0.09% but memory spiked. – WinterS Sep 19 '14 at 20:21
  • 2
    @WinterS It's probably those bindings. You need to look at your C# code and figure out the problem. I guarantee the problem is not in XAML. – B.K. Sep 19 '14 at 20:21
  • I suspect its the Bindings too, but I am not able to figure out yet. – WinterS Sep 19 '14 at 20:25
  • 2
    Well, everybody expects it is the bindings because that's all they can look at. Show us the reports you obtained from a memory profiler instead. – Hans Passant Sep 19 '14 at 20:30
  • 4
    I've run into problems in the past when displaying many TextBoxes on the screen at once in a Grid, and had two very different solutions to this problem. The first was caused by [updating the `.Text` frequently](http://stackoverflow.com/q/8733887/302677), and resolved by setting `IsUndoEnabled="False"` to disable tracking and storing `TextBox.Text` changes. The second solution involved displaying everything as a `TextBlock`, which uses much less memory than a `TextBox`, and changing the template to a `TextBox` when the user goes to edit it (such as clicking on the item). – Rachel Sep 19 '14 at 20:52
  • You could cut the amount of your xaml clutter by more than half pretty easily, and I forget, but is virtualization a default on ListBox for WPF? If not, you're probably going to want to look at that too at least. – Chris W. Sep 19 '14 at 21:00
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Sep 20 '14 at 02:28
  • @Rachel I also found the same thing, disabling undo makes it a little bit more responsive. – WinterS Sep 20 '14 at 08:28
  • Slow and uses too much memory are not the same problem. What problem are you trying to solve? And you could reduce the amount of syntax with styles. – paparazzo Sep 21 '14 at 19:03

0 Answers0