In this article I will make a WPF project with categories from Joomla! displayed as tree view.

Create new WPF project, in my case I name it TreeViewDetailed. First I will load top level categories. For this part we will need just treeview, XAML looks like this:

<Window x:Class="TreeViewDetailed.View.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:viewModel="clr-namespace:TreeViewDetailed.ViewModel"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.Resources>
            <viewModel:TreeViewDetailedViewModel x:Key="TreeViewDetailedViewModel" />
        </Grid.Resources>
        <TreeView DataContext="{StaticResource TreeViewDetailedViewModel}" ItemsSource="{Binding CategoriesList}"/>
    </Grid>
</Window>

Here notice how I declared TreeView:

<TreeView DataContext="{StaticResource TreeViewDetailedViewModel}" ItemsSource="{Binding CategoriesList}"></TreeView>

Now, we will need model for our CategoriesList property:

public class CategoriesListModel
{
	public string Name { get; set; }
	public int Id { get; set; }
	public List<CategoriesListModel> Categories { get; set; }
}

Note line:

List<CategoriesListModel> Categories { get; set; }

That is because each category can have parent category, in this first part we don't need that line, we will need it later when we start loading leafs (tree view items).

Next thing is view model which we have to define. First lets declare connection string which we will use to connect to our Joomla! MySQL database. Open App.config file:

...and write your connection string in my case App.config looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <connectionStrings>
    <add name="JoomlaCon"
      connectionString="
        SERVER=myServer;
        DATABASE=myDatabase;
        UID=myUid;
        PASSWORD=myPass;
        Convert Zero Datetime=True;
      "
    />
  </connectionStrings>
  
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
</configuration>

Here note:

Convert Zero Datetime=True

without that you will receive error:

Unable to convert MySQL date/time value to System.DateTime

As I already explained here.

Next thing which you will need is to add mySql support to your references, you can download it as I explained here, or you can install it over nuget:

Then search for mySql:

After that your reference list should look like:

 

 Now we can start building our view model:

public class TreeViewDetailedViewModel
{
	private string JoomlaConStr = ConfigurationManager.ConnectionStrings["JoomlaCon"].ConnectionString;
	public List<CategoriesListModel> CategoriesList { get; set; }
	public TreeViewDetailedViewModel()
	{
		var connection = new MySqlConnection(JoomlaConStr);

		string sql = "select * from jos_categories where level = 0 order by id ";

		var cmdSel = new MySqlCommand(sql, connection);

		connection.Open();

		MySqlDataReader dataReader = cmdSel.ExecuteReader();

		CategoriesList = new List<CategoriesListModel>();
		var i = 0;
		while (dataReader.Read())
		{
			i++;

			CategoriesList.Add(new CategoriesListModel
			{
				Name = dataReader["title"].ToString(),
				Id = int.Parse(dataReader["id"].ToString())
			});
		}
	}
}

Here note line:

private string JoomlaConStr = ConfigurationManager.ConnectionStrings["JoomlaCon"].ConnectionString;

with ConfigurationManager.ConnectionStrings["JoomlaCon"].ConnectionString we are calling connection string which we defined in App.config

then note line:

private List<CategoriesListModel> CategoriesList;

as you can see our CategoriesList property is defined as list of CategoriesListModel.

Now, when you start the application you should see something like:

Next thing which we will need is to display nodes in some human readable format.

We will achieve this if we change our XAML to:

<Window x:Class="TreeViewDetailed.View.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:viewModel="clr-namespace:TreeViewDetailed.ViewModel"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        xmlns:treeViewModel="clr-namespace:TreeViewDetailed.Model"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.Resources>
            <viewModel:TreeViewDetailedViewModel x:Key="TreeViewDetailedViewModel" />
        </Grid.Resources>
        <TreeView DataContext="{StaticResource TreeViewDetailedViewModel}" ItemsSource="{Binding CategoriesList}">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Categories}" DataType="{x:Type treeViewModel:CategoriesListModel}">
                    <TreeViewItem Header="{Binding Name}"/>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>
</Window>

Note that I added lines:

<TreeView.ItemTemplate>
	<HierarchicalDataTemplate ItemsSource="{Binding Categories}" DataType="{x:Type treeViewModel:CategoriesListModel}">
		<TreeViewItem Header="{Binding Name}"/>
	</HierarchicalDataTemplate>
</TreeView.ItemTemplate>

In these lines, notice:

<HierarchicalDataTemplate ItemsSource="{Binding Categories}" DataType="{x:Type treeViewModel:CategoriesListModel}">

Where Categories is (recursive) property defined in CategoriesListModel, and then:

<TreeViewItem Header="{Binding Name}"/>

This first step you can download from here.

Now, we have to change our view model so that we load all leafs, so first our categories list we will fill like this:

CategoriesList.Add(new CategoriesListModel
{
	Name = dataReader["title"].ToString(),
	Id = int.Parse(dataReader["id"].ToString()),
	Categories = new List<CategoriesListModel>()
});

Note that I added line Categories = new List<CategoriesListModel>().

Next thing which we need is recursive load of leafs:

private void CreateListRecursively(List<CategoriesListModel> CategoriesList)
{
	int i = -1;
	foreach (CategoriesListModel category in CategoriesList)
	{
		i++;

		var connection = new MySqlConnection(JoomlaConStr);

		string sql = "select * from jos_categories where parent_id = " + category.Id + " order by id ";

		var cmdSel = new MySqlCommand(sql, connection);

		connection.Open();

		MySqlDataReader dataReader = cmdSel.ExecuteReader();

		while (dataReader.Read())
		{
			CategoriesList[i].Categories.Add(new CategoriesListModel
			{
			Name = dataReader["title"].ToString(),
			Id = int.Parse(dataReader["id"].ToString()),
			Categories = new List<CategoriesListModel>()
			});
		}

		CreateListRecursively(CategoriesList[i].Categories);
	}
}

And that is all... Example project you can download from here.

Idea was to have one rectangle and on button click do hide / show that rectangle. Easiest way is with BooleanToVisibilityConverter.

XAML looks like this:

<Window x:Class="BooleanToVisibilityConverterExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:viewModel="clr-namespace:BooleanToVisibilityConverterExample.ViewModel"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.Resources>
            <viewModel:BooleanToVisibilityConverterExampleViewModel x:Key="BooleanToVisibilityConverterExampleViewModel" />
            <BooleanToVisibilityConverter x:Key="BoolToVis" />
        </Grid.Resources>
        
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="30" />
        </Grid.RowDefinitions>
        
        <Button DataContext="{StaticResource BooleanToVisibilityConverterExampleViewModel}" Command="{Binding OnClick}" Grid.Row="1" Content="Click Me!" VerticalContentAlignment="Bottom"/>

        <Rectangle x:Name="greenLine"
                    Height="25"
                    Width="25"
                    DataContext="{StaticResource BooleanToVisibilityConverterExampleViewModel}"
                    Visibility="{Binding MyHidden, Converter={StaticResource BoolToVis}, UpdateSourceTrigger=PropertyChanged}"
                    Fill="Green"/>
    </Grid>
</Window>

Note how I declared resource:

<BooleanToVisibilityConverter x:Key="BoolToVis" />

After that in rectangle declaration note:

Visibility="{Binding MyHidden, Converter={StaticResource BoolToVis}, UpdateSourceTrigger=PropertyChanged}"

There is no too much philosophy about code itself, basically everything is happening here:

MyHidden = !MyHidden;
OnPropertyChanged("MyHidden");

Property changed I explained here.

Example you can download from here.

There is also another solution, which I will not explain, since it is a bit more complicated, you have to implement IValueConverter, example for that version you can download from here, and to write that example I was this web site.

Idea was to write small app which will have one combo box where user will be able to change template for some list of buttons.

Instead I just made one project where I merged knowledge from this, this, this, and this article.

That is just for my future reference. Example project you can download from here.

Now idea is to have one control inside ItemsControl, and everything that inside UserControl, something like:

<UserControl x:Class="MyUserControl.myControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
      
      <ItemsControl ItemsSource="{Binding myLabels}">
        <ItemsControl.ItemTemplate>
          <DataTemplate>
            <Label Content="{Binding DataContext.myContent, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
          </DataTemplate>
        </ItemsControl.ItemTemplate>
      </ItemsControl>
      
    </Grid>
</UserControl>

Here notice line:

<Label Content="{Binding DataContext.myContent, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>

This line was taken from here.

My MainWindow.xaml looks like this:

<Window x:Class="UserControlDataContext.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:myUserControl="clr-namespace:MyUserControl;assembly=MyUserControl"
        xmlns:viewModel="clr-namespace:UserControlDataContext.ViewModel"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
      
        <Grid.Resources>
          <viewModel:UserControlDataContextViewModel x:Key="UserControlDataContextViewModel" />
        </Grid.Resources>
      
        <myUserControl:myControl DataContext="{Binding Source={StaticResource UserControlDataContextViewModel}}"/>
      
    </Grid>
</Window>

and view model like:

public class UserControlDataContextViewModel
{
	public string myContent { get; set; }

	public IEnumerable<string> myLabels { get; set; }

	public UserControlDataContextViewModel()
	{
		myContent = "test";
		myLabels = new[] { "test1", "test2" };
	}
}

Example project you can download from here.