Silverlight中TreeView,TreeViewItem,HierarchalDataTemplate的详细用法

来源:互联网 发布:意大利海关数据 编辑:程序博客网 时间:2024/04/30 11:26

转载自:http://blogs.silverlight.net/blogs/justinangel/archive/2008/11/18/silverlight-toolkit-treeview-treeviewitem-amp-hierarchaldatatemplate.aspx



Hi folks,

 

I’d like to go over the TreeView control which is part of the new Silverlight Toolkit (http://www.codeplex.com/Silverlight).
We’ll talk about the TreeView control itself, how to style the TreeViewItem and what is HierarchalDataTemplate all about.  

Recommended reading before reading this article

1. Silverlight Toolkit: HeaderedContentControl & HeaderedItemsControl

 

 

Setup

1. Create a new project.

image2_thumb2

 

2. Add a reference to the Silverlight Controls assembly (Microsoft.Windows.Controls.dll) which can be downloaded athttp://codeplex.com/Silverlight.

image10_thumb2  image_thumb3313

 

3. Look under "Custom Controls" In the Blend Asset Library.

image13_thumb2

 

4. Add a TreeView to the Page.

image

 

And here's the XAML Blend generated for us:

<UserControl    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    mc:Ignorable="d"    x:Class="SilverlightControlsNovember2008.TreeViewPage"    d:DesignWidth="640" d:DesignHeight="480"    xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls"    xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows">    <Grid x:Name="LayoutRoot" Background="#FFFFFFFF">        <controls:TreeView Margin="79,98,0,0" VerticalAlignment="Top" Height="200" Width="120" HorizontalAlignment="Left"/>    </Grid></UserControl>

Manually Adding New Textual TreeViewItems to a TreeView

Let’s add some TreeViewItems to our TreeView that will reflect a family’s genealogy tree.  like so:

image

 

We’ll right click on TreeView –> Add TreeViewItem.

image

And we can see that we indeed got a new TreeViewItem nested under or TreeView:

image

 

Next, we’ll go to the TreeViewItem’s properties and set Header to “Sally” andIsExpanded to true.

image 

 

Here’s the XAML blend generated for us up until now:

<controls:TreeView  Height="200" Width="120">    <controls:TreeViewItem IsExpanded="True" Header="Sally"/></controls:TreeView>

Now we’d like to add “John” as a child TreeViewItem of “Sally”.

We’ll Right click on “Sally” TreeViewItem –> Add TreeViewItem.

image

And we got another nested note inside the previous TreeViewItem:

image

 

We’ll edit it’s Header to “John” and we’ll keep IsExpanded to false, because it has no nested nodes.

image

 

We’ll keep it up until we get the following TreeView:

image

 

Let’s run our sample:

image

And we can start collapsing, expanding & Selecting TreeViewItems:

image

(In the above sample, Greg is collapsed, and John is selected)

 

And here’s the XAML Blend generated for us:

<controls:TreeView Height="200" Width="120">    <controls:TreeViewItem IsExpanded="True" Header="Sally">        <controls:TreeViewItem Header="John"/>        <controls:TreeViewItem Header="Greg" IsExpanded="True">            <controls:TreeViewItem Header="Linda"/>            <controls:TreeViewItem Header="Darren"/>        </controls:TreeViewItem>        <controls:TreeViewItem Header="Allice" IsExpanded="True">            <controls:TreeViewItem Header="Neil"/>        </controls:TreeViewItem>    </controls:TreeViewItem></controls:TreeView>

Editing the TreeViewItem’s Header property in Visual Studio XAML Editor

Now it’s time to uncover the horrible truth – Sally and her children are all aliens. The green “blip blip” kind.

This is how our TreeView should look like when we’re done:

image 

 

Blend currently does not support editing the Header property in a visual way. So we’ll open up Visual Studio’s XAML editor for that.

Right click on “TreeViewPage.xaml” (which is our page) in the Blend project tab –> Edit In Visual Studio.

image

 

And in a few second we’ll see this screen:

image

 

We’ll start off by changing the first TreeViewItem:

<controls:TreeViewItem IsExpanded="True" Header="Sally">

First, we’ll expand the Header property to allow XAML content:
<controls:TreeViewItem IsExpanded="True">    <controls:TreeViewItem.Header></controls:TreeViewItem.Header>

We’ll fill in the “Sally” content:
<controls:TreeViewItem IsExpanded="True">    <controls:TreeViewItem.Header>        <TextBlock Text="Sally" />    </controls:TreeViewItem.Header>

nd our TreeView still looks exactly the same:

image

 

Now we’d like to add the image of our Alien, but the Header can only contain a single element.
So we’ll group the <Image> and the <TextBlock> in a horizontal <StackPanel>.

<controls:TreeViewItem.Header>

    <StackPanel Orientation="Horizontal">

        <TextBlock Text="Sally" />

    </StackPanel>

</controls:TreeViewItem.Header>

Now that we have a container in the Header, we’ll add the <Image> tag.

<controls:TreeViewItem.Header>

    <StackPanel Orientation="Horizontal">

        <Image Source="Alien1.png" />

        <TextBlock Text="Sally" />

    </StackPanel>

</controls:TreeViewItem.Header>

In our Visual Studio preview windows we can see the following image:

image

Well, The text is too small for our picture. So let’s change the FontSize for theTreeViewto 22.

<controls:TreeViewFontSize="22" Height="200" Width="120">

 

image

We can see the Horizontal and Vertical Scrollbars appear because now our TreeViewItems are bigger than the TreeView. We’ll change the TreeViewWidth & Heightaccordingly. 

<controls:TreeView FontSize="22" Height="350" Width="250">

 

Now our TreeView looks much better:

image

 

here’s our XAML up until now:

In our Visual Studio preview windows we can see the following image:

image

Well, The text is too small for our picture. So let’s change the FontSize for the TreeView to 22.

<controls:TreeView FontSize="22" Height="200" Width="120">

 

image

We can see the Horizontal and Vertical Scrollbars appear because now our TreeViewItems are bigger than the TreeView. We’ll change the TreeView Width & Height accordingly. 

<controls:TreeView FontSize="22" Height="350" Width="250">

 

Now our TreeView looks much better:

image

 

here’s our XAML up until now:

<controls:TreeView FontSize="22" Height="350" Width="250" Margin="84,101,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">    <controls:TreeViewItem IsExpanded="True">       <controls:TreeViewItem.Header>            <StackPanel Orientation="Horizontal">                <Image Source="Alien1.png" />                <TextBlock Text="Sally" />            </StackPanel>        </controls:TreeViewItem.Header>        <controls:TreeViewItem Header="John"/>        <controls:TreeViewItem Header="Greg" IsExpanded="True">            <controls:TreeViewItem Header="Linda"/>            <controls:TreeViewItem Header="Darren"/>        </controls:TreeViewItem>        <controls:TreeViewItem Header="Allice" IsExpanded="True">            <controls:TreeViewItem Header="Neil"/>        </controls:TreeViewItem>    </controls:TreeViewItem></controls:TreeView>

We’ll repeat the process of editing an Image for the other 6 TreeViewItems. Than we’ll run our application.

image

 

here’s the XAML we wrote:

<controls:TreeView FontSize="22" Height="350" Width="250" Margin="84,101,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">    <controls:TreeViewItem IsExpanded="True">        <controls:TreeViewItem.Header>            <StackPanel Orientation="Horizontal">                <Image Source="Alien1.png" />                <TextBlock Text="Sally" />            </StackPanel>        </controls:TreeViewItem.Header>                <controls:TreeViewItem>                    <controls:TreeViewItem.Header>                        <StackPanel Orientation="Horizontal">                            <Image Source="Alien2.png" />                            <TextBlock Text="John" />                        </StackPanel>                    </controls:TreeViewItem.Header>                </controls:TreeViewItem>                <controls:TreeViewItem IsExpanded="True">                    <controls:TreeViewItem.Header>                        <StackPanel Orientation="Horizontal">                            <Image Source="Alien3.png" />                            <TextBlock Text="Greg" />                        </StackPanel>                    </controls:TreeViewItem.Header>                    <controls:TreeViewItem>                        <controls:TreeViewItem.Header>                            <StackPanel Orientation="Horizontal">                                <Image Source="Alien4.png" />                                <TextBlock Text="Linda" />                            </StackPanel>                        </controls:TreeViewItem.Header>                    </controls:TreeViewItem>                    <controls:TreeViewItem>                        <controls:TreeViewItem.Header>                            <StackPanel Orientation="Horizontal">                                <Image Source="Alien5.png" />                                <TextBlock Text="Darren" />                            </StackPanel>                        </controls:TreeViewItem.Header>                    </controls:TreeViewItem>                    </controls:TreeViewItem>        <controls:TreeViewItem IsExpanded="True">                    <controls:TreeViewItem.Header>                        <StackPanel Orientation="Horizontal">                            <Image Source="Alien6.png" />                            <TextBlock Text="Allice" />                        </StackPanel>                    </controls:TreeViewItem.Header>                    <controls:TreeViewItem>                        <controls:TreeViewItem.Header>                            <StackPanel Orientation="Horizontal">                                <Image Source="Alien7.png" />                                <TextBlock Text="Neil" />                            </StackPanel>                        </controls:TreeViewItem.Header>                    </controls:TreeViewItem>        </controls:TreeViewItem>    </controls:TreeViewItem></controls:TreeView>

We can definitely see that we’ve did some copy & paste here. Next we’ll see how we can use DataBinding to remove this repeatable code. 

 

 

Specifying a DataTemplate as the TreeView’s ItemTemplate

Well, now we’d like to remove that duplicated code by using some DataBinding.

We’ve got this Alien class:

public class Alien    {        public Alien(string name, string pictureUrl)        {            Name = name;            Picture = new BitmapImage(new Uri(pictureUrl, UriKind.Relative));        }         public string Name { get; set;  }        public BitmapImage Picture { get; set; }    }

Pretty simple, we’ve got a Name property, and a Picture property the we’re settings with way Silverlight uses for Image.Source databinding.

We’ll jump back to Blend.

image

And clear all the Items from the TreeViewItem by selecting the first TreeViewItem and deleting it.

image

image

 

Now that we have an empty TreeView, we’d like to set a x:Name so we can setup the TreeView‘sDataContext from our Code-behind.

image

 

We’ll set the TreeView ItemSource to run on a collection of aliens.

void TreeViewPage_Loaded(object sender, RoutedEventArgs e){    trvAliens.ItemsSource = new List<Alien>()                                {                        new Alien("Sally", "Alien1.png"),                        new Alien("John", "Alien2.png"),                        new Alien("Greg", "Alien3.png"),                        new Alien("Linda", "Alien4.png"),                        new Alien("Darren", "Alien5.png"),                        new Alien("Alice", "Alien6.png"),                        new Alien("Neil", "Alien7.png"),                                };}

Now, we can finally get down to business – changing the TreeView’s ItemTemplate.

Right Click on TreeView –> Edit Other Templates –> Edit Generated Items (ItemTemplate) –> Create Empty.

image

We’ll call our new Template AlienTemplate.

image

We can see that we have an empty DataTemplate:

image

 

First, we’ll Change the Grid to a Horizontal StackPanel.

Right Click Grid –> Change Layout Type –> StackPanel.

image image

 

Next we’ll add an Image control.

image

And we’ll want to DataBind it’s Source Property to Alien.Picture property.

Click Advanced Property options next to Source.

image

Select “Custom Expression”.

image

And put in “{Binding Picture}”.

image

 

Next we’ll add a TextBlock and Bind it’s Text property to “{Binding Name}”.

image -->image –>

image -->image

 

Let’s run this sample:

image

 

Here’s the XAML Blend Generated for our TreeView:

<UserControl.Resources>    <DataTemplate x:Key="AlienTemplate">        <StackPanel Orientation="Horizontal">            <Image Source="{Binding Path=Picture}"/>            <TextBlock Text="{Binding Path=Name}"/>        </StackPanel>    </DataTemplate></UserControl.Resources>Here’s our Code-behind:void TreeViewPage_Loaded(object sender, RoutedEventArgs e){    trvAliens.ItemsSource = new List<Alien>()                                {                        new Alien("Sally", "Alien1.png"),                        new Alien("John", "Alien2.png"),                        new Alien("Greg", "Alien3.png"),                        new Alien("Linda", "Alien4.png"),                        new Alien("Darren", "Alien5.png"),                        new Alien("Alice", "Alien6.png"),                        new Alien("Neil", "Alien7.png"),                                };}

And our current Alien Class:
public class Alien{    public Alien(string name, string pictureUrl)    {        Name = name;        Picture = new BitmapImage(new Uri(pictureUrl, UriKind.Relative));    }     public string Name { get; set;  }    public BitmapImage Picture { get; set; }} 

Specifying a HierarchalDataTemplate as a TreeView’s ItemTemplate in Visual Studio XAML Editor

In case you haven’t noticed, our current TreeView is pretty flat. It only has 1 level. And we’d like to get a similar TreeView to the one we previously had, with Nested TreeViewItems.

We’ll start by changing our CLR Alien Type:

    public class Alien    {        public Alien(string name, string pictureUrl, params Alien[] children)        {            Name = name;            Picture = new BitmapImage(new Uri(pictureUrl, UriKind.Relative));           Children = children;        }         public string Name { get; set; }        public BitmapImage Picture { get; set; }       public Alien[] Children { get; set;  }    }

All we did is add a property that is collection of Aliens that are the Children of that Alien.

 

Now that we’ve got a Hierarchical Alien class, we’ll change our code behind to use it:

void TreeViewPage_Loaded(object sender, RoutedEventArgs e){    trvAliens.ItemsSource = new List<Alien>()                        {                new Alien("Sally", "Alien1.png",                    new Alien("John", "Alien2.png"),                   new Alien("Greg", "Alien3.png",                        new Alien("Linda", "Alien4.png"),                        new Alien("Darren", "Alien5.png")                            ),                    new Alien("Alice", "Alien6.png",                        new Alien("Neil", "Alien7.png")                            )                          )                        };} 

The next part of changing our ItemTemplate is not supported by Blend. so we’re back at editing XAML in Visual Studio XAML Editor.

This is our current DataTemplate:

<DataTemplate x:Key="AlienTemplate">    <StackPanel Orientation="Horizontal">        <Image Source="{Binding Path=Picture}"/>        <TextBlock Text="{Binding Path=Name}"/>    </StackPanel></DataTemplate>


Let’s change it to a HierarchicalDataTemplateL:

<controls:HierarchicalDataTemplate x:Key="AlienTemplate">    <StackPanel Orientation="Horizontal">        <Image Source="{Binding Path=Picture}"/>        <TextBlock Text="{Binding Path=Name}"/>    </StackPanel></controls:HierarchicalDataTemplate>


 

And we’ll need to point to our new Hierarchical CLR property – Children.

We’ll do that by Setting HierarchicalDataTemplate.ItemsSource to “{Binding Children}”.

<controls:HierarchicalDataTemplate x:Key="AlienTemplate" ItemsSource="{Binding Children}">    <StackPanel Orientation="Horizontal">        <Image Source="{Binding Path=Picture}"/>        <TextBlock Text="{Binding Path=Name}"/>    </StackPanel></controls:HierarchicalDataTemplate>


 

Let’s run the sample:

image

 

Here’s our XAML code for the TreeView (hasn’t changed during this sample):

<controls:TreeView FontSize="22" Height="350" Width="250" x:Name="trvAliens" ItemTemplate="{StaticResource AlienTemplate}"/>Here’s our updated ItemTemplate:<UserControl.Resources>    <controls:HierarchicalDataTemplate x:Key="AlienTemplate" ItemsSource="{Binding Children}">        <StackPanel Orientation="Horizontal">            <Image Source="{Binding Path=Picture}"/>            <TextBlock Text="{Binding Path=Name}"/>        </StackPanel>    </controls:HierarchicalDataTemplate></UserControl.Resources>


Here’s our updated Alien class:

public class Alien{    public Alien(string name, string pictureUrl, params Alien[] children)    {        Name = name;        Picture = new BitmapImage(new Uri(pictureUrl, UriKind.Relative));        Children = children;    }     public string Name { get; set; }    public BitmapImage Picture { get; set; }    public Alien[] Children { get; set; }}


And our updated Code-behind:

void TreeViewPage_Loaded(object sender, RoutedEventArgs e){    trvAliens.ItemsSource = new List<Alien>()                {        new Alien("Sally", "Alien1.png",            new Alien("John", "Alien2.png"),           new Alien("Greg", "Alien3.png",                new Alien("Linda", "Alien4.png"),                new Alien("Darren", "Alien5.png")                    ),            new Alien("Alice", "Alien6.png",                new Alien("Neil", "Alien7.png")                    )                  )                };}


 

 

 





原创粉丝点击