Silverlight 에서 TreeView,TreeView Item,HierarchalDataTemplate 의 상세 한 용법

다음으로 전송: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.
 
2. Add a reference to the Silverlight Controls assembly (Microsoft.Windows.Controls.dll) which can be downloaded athttp://codeplex.com/Silverlight.
  
 
3. Look under "Custom Controls" In the Blend Asset Library.
 
4. Add a TreeView to the Page.
 
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:
 
We’ll right click on TreeView –> Add TreeViewItem.
And we can see that we indeed got a new TreeViewItem nested under or TreeView:
 
Next, we’ll go to the TreeViewItem’s properties and set Header to “Sally” andIsExpanded to true.
 
 
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.
And we got another nested note inside the previous TreeViewItem:
 
We’ll edit it’s Header to “John” and we’ll keep IsExpanded to false, because it has no nested nodes.
 
We’ll keep it up until we get the following TreeView:
 
Let’s run our sample:
And we can start collapsing, expanding & Selecting TreeViewItems:
(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:
 
 
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.
 
And in a few second we’ll see this screen:
 
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:
 
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 and the in a horizontal .

   
       
   


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

   
       
       
   


In our Visual Studio preview windows we can see the following image:
Well, The text is too small for our picture. So let’s change the FontSize for theTreeView to 22.

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

 
Now our TreeView looks much better:
 
here’s our XAML up until now:

In our Visual Studio preview windows we can see the following 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">

 

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:

 

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.
 
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.
And clear all the Items from the TreeViewItem by selecting the first TreeViewItem and deleting it.
 
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.
 
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.
We’ll call our new Template AlienTemplate.
We can see that we have an empty DataTemplate:
 
First, we’ll Change the Grid to a Horizontal StackPanel.
Right Click Grid –> Change Layout Type –> StackPanel.
 
 
Next we’ll add an Image control.
And we’ll want to DataBind it’s Source Property to Alien.Picture property.
Click Advanced Property options next to Source.
Select “Custom Expression”.
And put in “{Binding Picture}”.
 
Next we’ll add a TextBlock and Bind it’s Text property to “{Binding Name}”.
--> –>
-->
 
Let’s run this sample:
 
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:
 
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")

                    )

                  )

                };

}

 
 

좋은 웹페이지 즐겨찾기