Use inline XAML with clr-namespace to create a Styled Treeview
Writing WPF code is made easier in VB because of the built in XML features (XAML is really XML). Here is a sample that creates a TreeView of some folders on disk.
Suppose we want to add a Trigger style that will fire when the mouse is over an item. We could do it in code:
Dim style As New Windows.Style
style.Triggers.Add(…)
but it’s more elegant to do it in XAML.
One problem when doing it with inline XML occurs when you want the XML to reference a type. The MyTVItem type inherits from the TreeViewItem class, and I want the style.TargetType to apply to my class, which is not defined in XAML.
IOW, we want the WPF XAML code to refer to the VB Type. The mechanism to do that is the clr-namespace, where we can specify the NameSpace and the Assembly in which the type is found.
Start VS 2010. File->New->Project->VB->Windows->WPF Application. Make sure to name it exactly “VBTVStyle” (or change the xmlns line below)
Replace the Mainwindow.Xaml.vb code with the code below.
Hit F5.
Observe what happens as you expand treeview branches with the keyboard and the mouse.
See also: What is your computer doing with all that memory? Write your own memory browser
<Code Sample>
Class MainWindow
Dim _tv As New MyTView
Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
Dim startPath = System.Environment.GetEnvironmentVariable("programfiles") + "\Microsoft Visual Studio 10.0"
Dim tItem = New MyTVItem(_tv) With {
.Header = startPath
}
_tv.Items.Add(tItem)
Dim dp = New DockPanel
dp.Children.Add(_tv)
Me.Content = dp
GetDirs(startPath, tItem)
tItem.IsExpanded = True ' expand 1st node
End Sub
Sub GetDirs(ByVal path As String, ByVal parent As ItemsControl)
Try
Dim dirs = IO.Directory.GetDirectories(path, "*.*", IO.SearchOption.TopDirectoryOnly)
For Each dirName In dirs
Dim tItem = New MyTVItem(_tv) With {
.Header = IO.Path.GetFileName(dirName)
}
parent.Items.Add(tItem)
GetDirs(dirName, tItem) ' recur
Next
Catch ex As Exception ' sometimes you get access denied
MessageBox.Show("Excpt: " + ex.Message + " " + If(String.IsNullOrEmpty(ex.StackTrace), "", ex.StackTrace))
End Try
End Sub
End Class
Class MyTView
Inherits TreeView
Sub New()
Dim XAMLStyle = _
<Style
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myns="clr-namespace:VBTVStyle;assembly=VBTVStyle"
TargetType="myns:MyTVItem">
<Setter Property="Foreground" Value="Blue"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
Try
Me.ItemContainerStyle = CType(Windows.Markup.XamlReader.Load(XAMLStyle.CreateReader), Windows.Style)
Catch ex As Exception
MessageBox.Show("Excpt: " + ex.Message + " " + If(String.IsNullOrEmpty(ex.StackTrace), "", ex.StackTrace))
End Try
End Sub
End Class
Class MyTVItem
Inherits TreeViewItem
Sub New(ByVal tv As MyTView)
Me.ItemContainerStyle = tv.ItemContainerStyle ' propagate to children
End Sub
End Class
</Code Sample>