Reputation: 4881
I have a project that requires the use of a treeview control. The control must have the ability for the text on each node to be formatted so the text can be multi coloured. This is best shown by the treeview used in outlook - see pic )
I historically have a windows forms control that I created to do this, my question is how easy is this to do in WPF without having to use 3rd party controls?
Upvotes: 2
Views: 2201
Reputation: 44048
I historically have a windows forms control that I created to do this
Forget winforms, it's a dinosaur technology that has not been improved since 2007, it is not intended to create Rich UIs (only poor ones), and that does not support anything and forces you to write too much code and achieve less. It does not support any kind of customization and is slow as hell.
All the horrible hacks required in winforms to do anything (such as "owner draw" and "P/Invoke", whatever that means) are completely irrelevant and unneeded in WPF.
I dont really want to invest a lot of time moving of winforms to wpf if what I want to do is either not possible or too difficult
People are doing things like this in WPF, which are completely impossible in winforms, so what you're talking about here is really a "piece of cake" for WPF.
First of all, if you're getting into WPF, you must forget the traditional too-much-code-for-anything winforms approach and understand and embrace The WPF Mentality.
Here is how you implement that in WPF:
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<TreeView ItemsSource="{Binding}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<DockPanel>
<!-- this Image Control will display the "icon" for each Tree item -->
<Image Width="18" Height="16" Source="{Binding ImageSource}"
DockPanel.Dock="Left" Margin="2"/>
<!-- this TextBlock will show the main "Caption" for each Tree item -->
<TextBlock Text="{Binding DisplayName}" FontWeight="Bold"
VerticalAlignment="Center"
x:Name="DisplayName" Margin="2"/>
<!-- this TextBlock will show the Item count -->
<TextBlock Text="{Binding ItemCount, StringFormat='({0})'}"
VerticalAlignment="Center" Margin="2" x:Name="ItemCount">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding ItemCountColor}"/>
</TextBlock.Foreground>
</TextBlock>
</DockPanel>
<HierarchicalDataTemplate.Triggers>
<!-- This DataTrigger will hide the ItemCount text
and remove the Bold font weight from the DisplayName text
when ItemCount is zero -->
<DataTrigger Binding="{Binding ItemCount}" Value="0">
<Setter TargetName="ItemCount" Property="Visibility" Value="Collapsed"/>
<Setter TargetName="DisplayName" Property="FontWeight" Value="Normal"/>
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Window>
Code Behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = DataSource.GetFolders();
}
}
Data Item:
public class Folder
{
public Folder(string displayName)
{
ImageSource = DataSource.Folder1;
Children = new List<Folder>();
ItemCountColor = "Blue";
DisplayName = displayName;
}
public Folder(string displayName, int itemCount): this(displayName)
{
ItemCount = itemCount;
}
public string DisplayName { get; set; }
public int ItemCount { get; set; }
public List<Folder> Children { get; set; }
public string ItemCountColor { get; set; }
public string ImageSource { get; set; }
}
DataSource class (A lot of boilerplate code that generates the tree entries and is not really part of the WPF side of things):
public static class DataSource
{
public const string Folder1 = "/folder1.png";
public const string Folder2 = "/folder2.png";
public const string Folder3 = "/folder3.png";
public const string Folder4 = "/folder4.png";
public static List<Folder> GetFolders()
{
return new List<Folder>
{
new Folder("Conversation History"),
new Folder("Deleted Items",102)
{
ImageSource = Folder2,
Children =
{
new Folder("Deleted Items #1"),
}
},
new Folder("Drafts",7)
{
ImageSource = Folder3,
ItemCountColor = "Green",
},
new Folder("Inbox",7)
{
ImageSource = Folder4,
Children =
{
new Folder("_file")
{
Children =
{
new Folder("__plans"),
new Folder("_CEN&ISO", 5),
new Folder("_DDMS", 1)
{
Children =
{
new Folder("Care Data Dictionary"),
new Folder("HPEN"),
new Folder("PR: Data Architecture"),
new Folder("PR: Hospital DS", 2),
new Folder("RDF"),
new Folder("Schemas"),
new Folder("Subsets"),
}
},
new Folder("_Interop")
{
Children =
{
new Folder("CDSA", 1),
new Folder("CPIS", 2),
new Folder("DMIC"),
new Folder("EOL"),
new Folder("... And so on..."),
}
}
}
}
}
}
};
}
}
Result:
string
, bool
, int
and List<T>
properties and does not have any dependencies on the UI framework at all, plus the DataSource
boilerplate, that does not have anything to do with WPF anyways.DataContext
to a List<Folder>
, the rest is achieved via DataBinding into the HierarchicalDataTemplate
that defines the Visual structure of the Tree items.File -> New Project -> WPF Application
and see the results for yourself, you will need to add the png
files and set their Build Action
to Resource
in your project:Once you know WPF, XAML and MVVM, you will NEVER want to go back to winforms again, and you'll realize how much valuable time you've lost all these years using dead technology.
Upvotes: 2