Showing posts with label WPF. Show all posts
Showing posts with label WPF. Show all posts

Friday, January 3, 2014

How to add dependency property for custom control in wpf

Introduction

Ever had problem that your custom controls dependency property is not getting updated when you changed it from the control? Probably most of the wpf developer already know it still sharing it because, I kind of lost few minutes in darkness when I found that my custom control is not updating the target dependency property.

Enough talk show me the code

Well here is the code!. Do you find anything wrong with it? Seems absolutely fine.

public static readonly DependencyProperty SelectedValueProperty =
DependencyProperty.Register(
"SelectedValue", typeof(DateTime?), typeof(DateTimePicker), new UIPropertyMetadata(null, OnPropertyChanged));

public DateTime? SelectedValue
{
get
{
return (DateTime?)this.GetValue(SelectedValueProperty);
}
set
{
this.SetValue(SelectedValueProperty, value);
}
}

Now, my view model has a notify property which looks like the below code


public DateTime CurrentDate
{
get
{
return this.currentDate;
}
set
{
this.currentDate = value;
this.OnPropertyChanged("CurrentDate");
}
}

And the data is hooked via xaml binding, code below.


<riteq:DateTimePicker IsEnabled="True"
VerticalAlignment
="Top"
SelectedValue
="{Binding CurrentDate}"
x:Name
="TimePicker"
DisplayMode
="DateOnly"
CalendarSelectionMode
="SingleDate">
</riteq:DateTimePicker>

Look a perfect setup for the code. And at first glance we didn’t had any problem, until we tested it. No matter what date I select from my custom date picker, it never updating the CurrentData property of the view model.


So there is something wrong with the controls property. I tested and debug the code seems to be the binding expression working fine.


Then I found a piece of code where I set the dependency property’s value. As soon as i set some thing there the property’s binding got broken.


Here is the code.


if (this.cal.IsDateChanged)
{
this.SelectedValue = this.cal.SelectedDate;
}

Its a simple property setting , but this was causing problem, then when crazy with googling and found an every easy fix for my problem.


And the problem is with my definition of the dependency property. I was using “UIPropertyMetadata”. I changed the definition of property change call back to  “FrameworkPropertyMetadata”, and every thing back to normal and working again. here is the revised defination for the dependency property.


public static readonly DependencyProperty SelectedValueProperty =
DependencyProperty.Register(
"SelectedValue",
typeof(DateTime?),
typeof(DateTimePicker),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnPropertyChanged));

So now we are using FrameworkPropertyMetadata as property meta data. And that is the fix for my problem.


Lesson

If you need any dependency that can be changed inside the control please use FrameworkPropertyMetadata for dependency property definition.

Friday, December 6, 2013

Boolean dependency property and its default value.

What’s up community, today I going to share a very basic trick that I learned while working on a wizard control. I would rather say that is a convention that i didn’t know previously. probably all the the WPF developer knows it, but just in case anyone needed it and wondering why its not working.

Enough talk, lets get in to the business, so i was developing a custom control, precisely a reusable wpf wizard control. And I introduced a dependency property for two mode of the UI here is how it looks.

public bool ShouldIgnoreStep
{
get { return (bool)GetValue(ShouldIgnoreStepProperty); }
set { SetValue(ShouldIgnoreStepProperty, value); }
}

public static readonly DependencyProperty ShouldIgnoreStepProperty =
DependencyProperty.Register(
"ShouldIgnoreStep", typeof(bool), typeof(RiteqWizardPage),
new PropertyMetadata(false, OnPropertyChanged));

private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RiteqWizardPage riteqWizardPage
= d as RiteqWizardPage;
if (e.Property.Name.Equals("ShouldIgnoreStep"))
{
if (e.NewValue != e.OldValue)
{
if (riteqWizardPage != null)
{
riteqWizardPage.OnShouldIgnoreStepChanged();
}
}
}
}


I started to use the property and set the properties value in codes. The first one that i used in the same container worked okay. But the subsequent controls in the same container was not getting property set as I have dependent code when the dependency property is changed I wish to do some work. But the OnPropertyChanged event on the other instance of the control returning always the default value.


I was about the pull all my hairs out, but suddenly it strikes in my head, the problem is the default value that I set to the dependency property.


Then I tried with default value to “null”, and it worked!. Wallah!. Well offcourse I had to use nullable bool to be able to set its default value to null.


In my opinion you should always use default property as to null unless you have some condition that requires to set default value.


public bool? ShouldIgnoreStep
{
get { return (bool?)GetValue(ShouldIgnoreStepProperty); }
set { SetValue(ShouldIgnoreStepProperty, value); }
}

public static readonly DependencyProperty ShouldIgnoreStepProperty =
DependencyProperty.Register(
"ShouldIgnoreStep", typeof(bool?), typeof(RiteqWizardPage),
new PropertyMetadata(null, OnPropertyChanged));

private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RiteqWizardPage riteqWizardPage
= d as RiteqWizardPage;
if (e.Property.Name.Equals("ShouldIgnoreStep"))
{
if (e.NewValue != e.OldValue)
{
if (riteqWizardPage != null)
{
riteqWizardPage.OnShouldIgnoreStepChanged();
}
}
}
}

Cheers! and happy coding.

Tuesday, August 14, 2012

WPF Single instance application, Now a piece of cake,

I was thinking of making a single instance application, and in WPF, googled for a minute and found out this,

WPF application Single Instance in one line of code for usage

http://wpfsingleinstance.codeplex.com/

features

Usage: WpfSingleInstance.Make(); or WpfSingleInstance.Make(SingleInstanceModes.ForEveryUser);
1. Add only a line of code (above) in the App.xaml.cs or in the main window.
2. Add a small static class in project (and a dummy enum SingleInstanceModes).
No additional inheritance in App class.
No App.xalm deleting.
No so redundant WCF and Remoting.
It works by the EventWaitHandle. Look in code, it's so simply.

I like it, hope all will like it.

Included a single cs file in my project named “WpfSingleInstance.cs”

then added the following line

public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
WpfSingleInstance.Make();

base.OnStartup(e);
}
}


Man!! couldn’t get better than this, thanks to the contributor,

Until next time. Bye bye

Friday, August 3, 2012

WPF Tree view binding how to stuff.

Introduction

Treeview is a very useful control, yet not that much used in real life scenario, however; it has a very good potential and the control is very customizable. Even though it has some disadvantages over some special category of data but none the less this control is a great addition to WPF default control set. In this particular article we will look at some basic functionality that WPF Tree view can provides, in particular we will take a look at the binding options. 

Basic Uses

Bellow I have given a simple code, that shows how to add a treeview in XAML. The Treeview Items are also defined as as a child nodes.

<Window x:Class="WPFTreeView.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">
<Grid>
<TreeView Height="287"
HorizontalAlignment="Left"
Margin="12,12,0,0"
Name="treeView1"
VerticalAlignment="Top"
Width="479">
<TreeViewItem Header="Bing">
<TreeViewItem Header="A" />
<TreeViewItem Header="B" />
<TreeViewItem Header="C" />
</TreeViewItem>
<TreeViewItem Header="Google" >
<TreeViewItem Header="D" />
<TreeViewItem Header="E" />
</TreeViewItem>
<TreeViewItem Header="Yahoo" >
<TreeViewItem Header="F" />
</TreeViewItem>
</TreeView>
</Grid>
</Window>


 

If you want to Populate the tree view and its node from c# code bellow I have listed few line of code to demonstrate how to do that.


using System.Windows;
using System.Windows.Controls;

namespace WPFTreeView
{
public partial class WindowTreeViewFromCodexaml
{
private TreeView _treeView;

public WindowTreeViewFromCodexaml()
{
InitializeComponent();
BuildTreeView();
BuildTreeViewNodes(0,_treeView.Items);
}

private void BuildTreeViewNodes(int level, ItemCollection itemCollection)
{
if(level==3)
return;

for (int i = 0; i < 3; i++)
{
var item = new TreeViewItem();
item.Header = string.Format("Item {0}", i + 1);
BuildTreeViewNodes(level+1,item.Items);
itemCollection.Add(item);
}
}

private void BuildTreeView()
{
TreeViewContainer.Children.Clear();
_treeView = new TreeView();
_treeView.HorizontalAlignment = HorizontalAlignment.Left;
_treeView.Margin = new Thickness(12, 12, 0, 0);
_treeView.Name = "treeView1";
_treeView.VerticalAlignment = VerticalAlignment.Top;
TreeViewContainer.Children.Add(_treeView);
}
}
}


Binding to a source


In this section we would see how we can bind a Treeview to a data source which has a hierarchical structure. For this scenario let’s Consider the following example. “ We want to display employee information as hierarchical data. The corresponding xaml and c# code is given bellow. 


XAML code


<Window x:Class="WPFTreeView.WindowTreeViewWithItemSource"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowTreeViewWithItemSource" Height="300" Width="300">
<Window.Resources>
<HierarchicalDataTemplate x:Key="ItemTemplate" ItemsSource="{Binding Employees}" >
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}"></CheckBox>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<DockPanel LastChildFill="True">
<TreeView
Name="treeView1"
ItemTemplate="{StaticResource ItemTemplate}"
ItemsSource="{Binding Employees}">
</TreeView>
</DockPanel>
</Grid>
</Window>


Above  Xaml code shows declaration of WPF treeview where ItemSource is Employee Dependency Property. But we would assign the item source from code. And this would work perfectly as we override the binding with hard code source. We have also defined a item template for each tree view item node. Bellow the corresponding c# code is given.


C# code


public partial class WindowTreeViewWithItemSource
{
public WindowTreeViewWithItemSource()
{
InitializeComponent();
LoadData();
}

private void LoadData()
{
var employees = new List();
for (int i =1; i <= 100; i++)
{
var manager = new Employee {Name = string.Format("Manager {0}", i.ToString())};
for (int j = 1; j <= 100; j++)
{
var lead = new Employee { Name = string.Format("Team Lead {0}", i.ToString()) };
for (int k = 0; k < 100; k++)
{
var junior = new Employee { Name = string.Format("Developer {0}", i.ToString())};
lead.Employees.Add(junior);
}
manager.Employees.Add(lead);
}
employees.Add(manager);
}
treeView1.ItemsSource = employees;
}
}

public class Employee
{
public Employee()
{
Employees = new List();
}
public string Name { get; set; }
public string Department { get; set; }
public int Age { get; set; }
public string Designation { get; set; }
public string Email { get; set; }
public DateTime DateOfJoin { get; set; }
public double Salary { get; set; }
public List Employees { get; private set; }
}


In above code we have defined a custom user type named “Employee” and constructed a demo hierarchy data, and finally assigned to the item source of the treeview. Note that here we did assigned itemsouce directly. If we want to use binding in that case we have to use mvp (model view presenter) or MVVM ( Model View ViewModel) pattern.


public partial class WindowTreeViewWithItemSourceBinding
{
public WindowTreeViewWithItemSourceBinding()
{
InitializeComponent();
this.DataContext = new TreeViewPresenter();
}
}

public class TreeViewPresenter:DependencyObject
{
public TreeViewPresenter()
{
LoadData();
}
private void LoadData()
{
var employees = new List<Employee>();
for (int i = 1; i <= 100; i++)
{
var manager = new Employee { Name = string.Format("Manager {0}", i.ToString()) };
for (int j = 1; j <= 100; j++)
{
var lead = new Employee { Name = string.Format("Team Lead {0}", i.ToString()) };
for (int k = 0; k < 100; k++)
{
var junior = new Employee { Name =
                    string.Format("Developer {0}", i.ToString()) };
lead.Employees.Add(junior);
}
manager.Employees.Add(lead);
}
employees.Add(manager);
}
Employees = employees;
}
public List<Employee> Employees
{
get { return (List<Employee>)GetValue(EmployeesProperty); }
set { SetValue(EmployeesProperty, value); }
}

public static readonly DependencyProperty EmployeesProperty =
DependencyProperty.Register("Employees", typeof(List<Employee>),
typeof(TreeViewPresenter), new UIPropertyMetadata(null));
}


Summery


In this short article we have seen how to use WPF tree view and some usages of WPF tree view as far as the binding and populating tree view is concern.


References


MSDN Help


Friday, July 27, 2012

How to Customize the look and feel of WPF Tree view? [Part 2]

Styling the expend collapse icon

This part is not easy, we have to open the box and see for our self what’s inside? fear not!! we can open its internal structure using expression blend and then modify the required stuff, our goal in this section is to replace the default expand collapse icon with something more friendly, for instance a plus and minus icon would do for now I guess.
Lets open the project in expression blend navigate to our desired project and then open the desired window, in our case we have main window, a simple tree view control is added. navigate to the tree view just like the image shown here, then select one of the TreeViewItem , if there is no add a demo one. Then right click and select edit template, and select edit a copy.
TreeViewTemplate_thumb2
It will quickly extend the style and bring out the desired styles in a resource file. if you mention it. well here is the xaml looks like after I have edited the default template.
image_thumb5
Looks rusty! but you have to consider that I am a developer not a designer, designers will come out with awesome design to look it good. well our main concern is the know now. Bello I have listed the complete xaml for the edited TreeViewItem Template.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Canvas x:Key="FolderIcon" x:Shared="false" Width="16" Height="16" ClipToBounds="True">
        <Rectangle Fill="BlanchedAlmond" Canvas.Left="0" Canvas.Top="0" Height="15" Width="15">
        </Rectangle>
    </Canvas>
    <Style x:Key="TreeViewItemFocusVisual">
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate>
                    <Rectangle/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <PathGeometry x:Key="TreeArrow" Figures="M0,0 L0,6 L6,0 z"/>
    <Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
        <Setter Property="Focusable" Value="False"/>
        <Setter Property="Width" Value="16"/>
        <Setter Property="Height" Value="16"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ToggleButton}">
                    <Border Height="16" Width="16" BorderBrush="Gray" BorderThickness="1" Background="Transparent">
                        <Canvas Name="ExpandPath">
                            <Rectangle x:Name="virticalbar" Canvas.Top="1" Canvas.Left="6.5" Width="1" Height="12" Fill="Gray"></Rectangle>
                            <Rectangle Canvas.Left="1" Canvas.Top="7" Width="12" Height="1" Fill="Gray"></Rectangle>
                        </Canvas>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                        </Trigger>
                        <Trigger Property="IsChecked" Value="True">
                            <Setter Property="Visibility" TargetName="virticalbar" Value="Hidden"></Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style TargetType="{x:Type TreeViewItem}">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="Padding" Value="1,0,0,0"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="FocusVisualStyle" Value="{StaticResource TreeViewItemFocusVisual}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TreeViewItem}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition MinWidth="19" Width="Auto"/>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <ToggleButton x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}"/>
                        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="1" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                            <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Margin="4,0,0,0"/>
                        </Border>
                        <ItemsPresenter x:Name="ItemsHost" Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsExpanded" Value="false">
                            <Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
                        </Trigger>
                        <Trigger Property="HasItems" Value="false">
                            <Setter Property="Visibility" TargetName="Expander" Value="Hidden"/>
                        </Trigger>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsSelected" Value="true"/>
                                <Condition Property="IsSelectionActive" Value="false"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                        </MultiTrigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="VirtualizingStackPanel.IsVirtualizing" Value="true">
                <Setter Property="ItemsPanel">
                    <Setter.Value>
                        <ItemsPanelTemplate>
                            <VirtualizingStackPanel/>
                        </ItemsPanelTemplate>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
    </Style>  
</ResourceDictionary>


Style the selected item


Now its time to style the selected item, if you carefully notice that by default when you select any items in WPF tree view you would see that there is a blue background appear behind the selected item. There is a good chance that the client or users will not like it in customized business solutions. Again since we have the whole skeleton of the TreeViewItem we would simply modify the default style.

Bellow I have listed the xaml part of the above full style but with a simple modification in one line only, note that we have a trigger were IsSelected Property is been queried with value True, where we have changed the default value to our customized value “Silver”.

<ControlTemplate.Triggers>
    <Trigger Property="IsExpanded" Value="false">
        <Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
    </Trigger>
    <Trigger Property="HasItems" Value="false">
        <Setter Property="Visibility" TargetName="Expander" Value="Hidden"/>
    </Trigger>
    <Trigger Property="IsSelected" Value="true">
        <Setter Property="Background" TargetName="Bd" Value="Silver"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
    </Trigger>
    <MultiTrigger>
        <MultiTrigger.Conditions>
            <Condition Property="IsSelected" Value="true"/>
            <Condition Property="IsSelectionActive" Value="false"/>
        </MultiTrigger.Conditions>
        <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    </MultiTrigger>
    <Trigger Property="IsEnabled" Value="false">
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
    </Trigger>
</ControlTemplate.Triggers>


The result is given bellow

Customize outer looks


Most easy part may be customize the outer look we can achieve this with the basic WPF knowledge's. All the container property such as Border Brush, Border thickness and Margin or Padding is available for modification. One interesting this is modification of the scroll bars, in this particular scenario you might want to again expression blend to customize the look and feel of the scroll content and scroll viewer scrollbars.

Summery


In this short article we have seen that how we can customize WPF tree view for our own way and they way we want it to be look like. The methods that has been used in this article is not prefect but one of the solution that can be implemented. Hopefully in future we can look more into it and customize even more to achieve our desired look and feel. If your have any feed back and suggestion please feel free to add in the comment section.

References


Friday, July 20, 2012

How to customize the look and feel of WPF tree view? [part1]

Why we need to customize Tree view?

Intention is to modify default look and feel so that we can use the tree view as custom purpose control not just hierarchical data structure, a good example could be a folder explorer.

In this short article we are going to see how to customize tree view look and feel. first we will look at how to customize the style of a tree view item, then move on to the expand and collapse icon, and lastly we would see how to style a selected item.

image_thumb11_thumb2

Styling the items

Lets say we want to display a icon before each tree view “item node” so that the user knows what type of file item it is, right now we have drive, directory and file, so we would add thee resources to display. Bellow a simple code is given to demonstrate how to read a file system, and then populate in a dependency object so that it can be bind to a tree view.

[Sample c# code]

using System.Collections.Generic;
using System.IO;
using System.Windows;

namespace WPFFolderExplorer
{
public class FileSystemPresenter : DependencyObject
{
public FileSystemPresenter()
{
LoadFileSystem();
}

private void LoadFileSystem()
{
var liteDirectoryInfos = new List<LiteDirectoryInfo>();
var driveInfos = DriveInfo.GetDrives();
foreach (var driveInfo in driveInfos)
{
if (driveInfo.DriveType == DriveType.Fixed)
{
var liteDirectoryInfo = new LiteDirectoryInfo
{
FileName = driveInfo.Name,
FileType = FileType.Drive
};
var info = new DirectoryInfo(driveInfo.Name);
var directoryInfos = info.GetDirectories();
foreach (var directoryInfo in directoryInfos)
{
liteDirectoryInfo.Files.Add(new LiteDirectoryInfo
{ FileName = directoryInfo.Name,
FileType = FileType.Folder });
}
liteDirectoryInfos.Add(liteDirectoryInfo);
}
}
FileSystem = liteDirectoryInfos;
}

public List<LiteDirectoryInfo> FileSystem
{
get { return (List<LiteDirectoryInfo>)GetValue(FileSystemProperty); }
set { SetValue(FileSystemProperty, value); }
}

public static readonly DependencyProperty FileSystemProperty =
DependencyProperty.Register("FileSystem", typeof(List<LiteDirectoryInfo>),
typeof(FileSystemPresenter), new UIPropertyMetadata(null));
}

public class LiteDirectoryInfo
{
public LiteDirectoryInfo()
{
Files = new List<LiteDirectoryInfo>();
}
public string FileName { get; set; }
public FileType FileType { get; set; }
public List<LiteDirectoryInfo> Files { get; set; }
}

public enum FileType
{
Drive,
Folder,
File
}
}

In the above code we have a enum FileType for distinguishing the file type. And a composite LiteDirectoryInfo where we have populated the directory structure. Finally After construction we preserved the data on FileSystem dependency property.


[Sample c# code for view c# part]


namespace WPFFolderExplorer
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
DataContext = new FileSystemPresenter();
}
}
}

Above code shows only the part where I have assigned our custom presenter to the WPFFolderExplorer’s DataContext to follow MVP Pattern (Model,View,Presenter) where model is our own local drives and file system.


[Sample code for XAML is Given here]


<Window x:Class="WPFFolderExplorer.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">
<Window.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Setter Property="Background" Value="Gray"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<DockPanel LastChildFill="True">
<Border DockPanel.Dock="Top" Height="30">
<!--tool bar will go here-->
</Border>
<TreeView DockPanel.Dock="Left" MinWidth="200" ItemsSource="{Binding FileSystem}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Files}">
<Border x:Name="itemBorder">
<DockPanel Margin="2">
<ContentControl Content="{DynamicResource FolderIcon}" DockPanel.Dock="Left"/>
<TextBlock Text="{Binding FileName}"></TextBlock>
</DockPanel>
</Border>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<ContentControl>
</ContentControl>
</DockPanel>
</Grid>
</Window>

In above xaml code its shown that how the binding with the presenter dependency is done. Also note that the item template is defined for a tree view.