Use colors in WPF to show virtual memory fragmentation
In this post What is your computer doing with all that memory? Write your own memory browser is sample code that shows how to create a WPF grid view of a memory map of a process. You can click on a column header to sort, and you can see the various loaded images and even a binary display of the actual memory.
We can modify that code to show the data in color very easily, using the magic of Data Binding.
Paste the code from the prior post’s sample into a new VB WPF Application. You might have to change the class name from “Window1” to “MainWindow”
Hit Ctrl-F5 to run it, dbl click on a process to show the memory map of that process.
Now let’s add some color: we add a few lines of code in 2 segments: a class that implements IValueConverter, and some code to modify the Style of the items contained in the ListView
Paste this class at the end of the file:
Public Class VMBgd
Implements IValueConverter
Public Function Convert(
ByVal value As Object,
ByVal targetType As System.Type,
ByVal parameter As Object,
ByVal culture As System.Globalization.CultureInfo
) As Object Implements System.Windows.Data.IValueConverter.Convert
Dim bgColor = Brushes.White
Dim lvitem = CType(value, ListViewItem)
Dim memType = CStr(ComponentModel.TypeDescriptor.
GetProperties(lvitem.DataContext)("Type").
GetValue(lvitem.DataContext)) ' get the value of the "Type" column
Select Case memType
Case "MEM_IMAGE"
bgColor = Brushes.Violet
Case "MEM_PRIVATE"
bgColor = Brushes.Yellow
Case "MEM_MAPPED"
bgColor = Brushes.PaleTurquoise
End Select
Return bgColor
End Function
Public Function ConvertBack(
ByVal value As Object,
ByVal targetType As System.Type,
ByVal parameter As Object,
ByVal culture As System.Globalization.CultureInfo
) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
Throw New NotImplementedException
End Function
End Class
And around line 160, find the “dp.Children.Add(New Browse” line and replace with this code:
'dp.Children.Add(New Browse(q, _
' delMouseMove:=AddressOf On_VirtmemMouseMove, _
' deldblclick:=AddressOf On_VirtmemDblClick))
Dim brow = New Browse(q, _
delMouseMove:=AddressOf On_VirtmemMouseMove, _
deldblclick:=AddressOf On_VirtmemDblClick)
Dim bgStyle = New Windows.Style(
GetType(ListViewItem)
) ' style for a ListViewItem
Dim binder = New Binding With {
.Converter = New VMBgd,
.RelativeSource = New RelativeSource(RelativeSourceMode.Self),
.Mode = BindingMode.OneTime
} ' Bind our color converter
Dim bgSetter = New Setter(ListViewItem.BackgroundProperty, Brushes.White) With {
.Value = binder
} ' BG bound to our binder
bgStyle.Setters.Add(bgSetter)
bgStyle.Setters.Add(
New Setter(
ListViewItem.MarginProperty,
New Thickness(0))
) ' space between rows
bgStyle.Setters.Add(
New Setter(
ListViewItem.BorderThicknessProperty,
New Thickness(0))
) ' space between rows
brow.ItemContainerStyle = bgStyle
dp.Children.Add(brow)
Now run it, select a process and see the colors! Click on BaseAddress to sort and browse around to groups of the Violet colored images and see how many of them are separated by a white Free region. If this region is less than 64k (0x10000), then that Virtual Memory address range fragment is unusable.
The pasted class VMBgd has the ability to return a color given an object. The TypeDescriptor class is used to get the properties of the ListView’s DataContext, which are the columns of the view. GetProperties returns a collection of PropertyDescriptors, and we want the Value of “Type” (which is the column indicating Memory Allocation Type from the Linq query (around line 156)) member.
An instance of the class is bound to the ListViewItem background color via a Setter in the Windows.Style for the ListView.ItemContainerStyle. When rendering the data, when the Background property is accessed, and it’s bound to our Converter which returns the desired color.
As an exercise, make these unusable regions a different color.
See also: