نظرة عامة حول قولبة البيانات

WPFطراز templating بيانات يوفر لك مرونة كبيرة إلى تعريف العرض التقديمي للبيانات الخاصة بك. WPFيكون لعناصر التحكم المضمنة وظائف إلى دعم cusإلىmization من بيانات العرض التقديمي. يوضح هذا الموضوع أولاً كيفية تعريف DataTemplate و ثم يقدم بعض ميزات قولبة البيانات الأخرى، مثل تحديد القوالب استناداً إلى منطق مخصص و دعم عرض البيانات ذات التسلسل الهرمي.

يشتمل هذا الموضوع على الأقسام التالية.

  • المتطلبات الأساسية
  • أساسيات قولبة البيانات
  • إضافة المزيد من DataTemplate
  • اختيار DataTemplate اعتماداً على الخصائص من كائن البيانات
  • styling و Templating ItemsControl
  • دعم البيانات ذات التسلسل الهرمي
  • موضوعات ذات صلة

المتطلبات الأساسية

يركز هذا الموضوع على ميزات قولبة البيانات و هو ليس مقدمة عن مفاهيم ربط البيانات. للحصول على معلومات حول أساسيات مفاهيم ربط البيانات, راجع نظرة عامة لربط البيانات.

DataTemplate i, حول العرض تقديمي للبيانات و يكون أحد العديد من الميزات التي يوفرها طراز التنميط و القولبة WPF. للحصول على مقدمة عن WPF طراز التنميط و القولبة مثل كيفية استخدام Style لتعيين خصائص في عناصر التحكم, راجع موضوع التنسيق و القولبة.

بالإضافة إلى ذلك، فإنه من المهم فهم Resources، التي بشكل أساسي هي ما يمكِّن كائنات مثل Style DataTemplate أن تكون قابلة لإعادة الاستخدام. لمزيد من المعلومات راجع نظرة عامة حول الموارد

أساسيات قولبة البيانات

يشتمل هذا القسم على الأقسام الفرعية التالية.

  • بدون DataTemplate
  • تعريف DataTemplate بسيطة
  • إنشاء DataTemplate كمورد
  • خاصية DataType

لعرض سبب أهمية DataTemplate, دعنا نمشي خلال مثال ربط البيانات. في هذا المثال، لدينا ListBox الذي يرتبط بقائمة كائنات Task. كل كائن Task يحتوي TaskName (سلسلة), Description (سلسلة), Priority (عدد صحيح) ، و خاصية من نوع TaskType، والتي هي Enum مع قيم Home و Work.

<Window x:Class="SDKSample.Window1"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:SDKSample"
  Title="Introduction to Data Templating Sample">
  <Window.Resources>
    <local:Tasks x:Key="myTodoList"/>


...



</Window.Resources>
  <StackPanel>
    <TextBlock Name="blah" FontSize="20" Text="My Task List:"/>
    <ListBox Width="400" Margin="10"
             ItemsSource="{Binding Source={StaticResource myTodoList}}"/>


...


  </StackPanel>
</Window>

بدون DataTemplate

بدون DataTemplate ، ListBox الخاص بنا له هذا المظهر:

لقطة شاشة لعينة من قوالب البيانات

ما يحدث أنه دون أي إرشادات خاصة, يستدعي ListBox بشكل افتراضي ToString عند محاولة عرض الكائنات في المجموعة. لذلك، إذا كان كائن Task يتجاوز أسلوب ToString, ثم ListBox يعرض تمثيل سلسلة لكل كائن مصدر في المجموعة الأساسية.

على سبيل المثال، إذا قامت فئة Task بتجاوز أسلوب ToString بهذه الطريقة، حيث name هو الحقل لخاصية TaskName:

Public Overrides Function ToString() As String
    Return _name.ToString()
End Function
public override string ToString()
{
    return name.ToString();
}

بذلك ListBox سيبدو كما يلي.

لقطة شاشة لعينة من قوالب البيانات

ومع ذلك، هذا يعتبر محدود و غير مرن. أيضاً، إذا كنت تقوم بربط إلى بيانات XML، لن تكون قادراً على تجاوز ToString.

تعريف DataTemplate بسيطة

الحل هو تعريف DataTemplate. إحدى الطرق للقيام بذلك هو بتعيين خاصية ItemTemplate من ListBox إلى DataTemplate. ما تحدده في DataTemplate الخاص بك يصبح بنية المرئية لكائن البيانات الخاص بك. DataTemplate التالي هو بسيط. نحن نعطي إرشادات أن كل عنصر يظهر كثلاثة عناصر TextBlock داخل StackPanel. كل عنصر TextBlock يرتبط بخاصية من فئة Task.

<ListBox Width="400" Margin="10"
         ItemsSource="{Binding Source={StaticResource myTodoList}}">
   <ListBox.ItemTemplate>
     <DataTemplate>
       <StackPanel>
         <TextBlock Text="{Binding Path=TaskName}" />
         <TextBlock Text="{Binding Path=Description}"/>
         <TextBlock Text="{Binding Path=Priority}"/>
       </StackPanel>
     </DataTemplate>
   </ListBox.ItemTemplate>
 </ListBox>

البيانات الأساسية للأمثلة في هذا الموضوع هي مجموعة من كائنات CLR. إذا كنت تقوم بربط إلى بيانات XML, المفاهيم الأساسية هي نفسها و لكن هناك فرق نحوي بسيط. على سبيل المثال، بدلاً من وجود Path=TaskName، ستقوم بتعيين XPath إلى @TaskName (إذا كان TaskName هو إحدى سمات عقدة XML الخاص بك).

الآن ListBox يبدو كما يلي.

لقطة شاشة لعينة من قوالب البيانات

إنشاء DataTemplate كمورد

في المثال أعلاه، نقوم تعريف DataTemplate ضمنياً. من الشائع أكثر تعريفها في مقطع الموارد بحيث يمكن أن تكون كائن قابل لإعادة الاستخدام كما في المثال التالي:

<Window.Resources>


...


<DataTemplate x:Key="myTaskTemplate">
  <StackPanel>
    <TextBlock Text="{Binding Path=TaskName}" />
    <TextBlock Text="{Binding Path=Description}"/>
    <TextBlock Text="{Binding Path=Priority}"/>
  </StackPanel>
</DataTemplate>


...


</Window.Resources>

الآن يمكنك استخدام myTaskTemplate كمورد كما في المثال التالي:

<ListBox Width="400" Margin="10"
         ItemsSource="{Binding Source={StaticResource myTodoList}}"
         ItemTemplate="{StaticResource myTaskTemplate}"/>

لأن myTaskTemplate هو مورد، الآن يمكنك استخدامه على عناصر التحكم الأخرى التي تحتوي خاصية التي تأخذ نوع DataTemplate. كما هو موضح أعلاه، لكائنات ItemsControl مثل ListBox، هي خاصية ItemTemplate. لكائنات ContentControl, هي خاصية ContentTemplate.

خاصية DataType

فئة DataTemplate تحتوي خاصية DataType التي تشبه جداً خاصية TargetType من فئة Style. لذلك، بدلاً من تحديد x:Key من DataTemplate في المثال أعلاه، يمكنك القيام بما يلي:

<DataTemplate DataType="{x:Type local:Task}">
  <StackPanel>
    <TextBlock Text="{Binding Path=TaskName}" />
    <TextBlock Text="{Binding Path=Description}"/>
    <TextBlock Text="{Binding Path=Priority}"/>
  </StackPanel>
</DataTemplate>

هذا DataTemplate يتم تطبيقه تلقائياً إلى كافة كائنات Task. لاحظ أن في هذه الحالة يتم تعيين x:Key ضمنياً. لذلك، إذا قمت بتعيين هذا DataTemplate قيمة x:Key, يتم تجاوز x:Key الضمني و DataTemplate قد لا يتم تطبيقه تلقائياً.

إذا كنت تقوم بربط ContentControl إلى مجموعة من كائنات Task, ContentControl لا يستخدم DataTemplate أعلاه تلقائياً. هذا لأن الربط على ContentControl بحاجة إلى المزيد من المعلومات لتميز ما إذا كنت تريد الربط إلى مجموعة كاملة أو كائنات فردية. إذا كان ContentControl الخاص بك هو تعقب تحديد نوع ItemsControl، يمكنك تعيين خاصية Path من ربط ContentControl إلى "/" للإشارة إلى انك مهتم بالعنصر الحالي. على سبيل المثال ، راجع كيفية القيام بما يلي: ربط مجموعة و عرض معلومات اعتماداً على الاختيار. وإلا ستحتاج إلى تحديد DataTemplate بشكل صريح عن طريق تعيين خاصية ContentTemplate.

خاصية DataType مفيدة خاصة إذا كان لديك CompositeCollection من أنواع مختلفة من كائنات البيانات. على سبيل المثال ، راجع كيفية القيام بما يلي: تنفيذ مركب المجموعة.

إضافة المزيد من DataTemplate

حالياً تظهر البيانات بالمعلومات الضرورية و لكن يمكن دائماً التحسين. دعنا نحسن العرض التقديمي عن طريق إضافة Border، Grid، و بعض عناصر TextBlock التي تصف البيانات التي يتم عرضها.


<DataTemplate x:Key="myTaskTemplate">
  <Border Name="border" BorderBrush="Aqua" BorderThickness="1"
          Padding="5" Margin="5">
    <Grid>
      <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
      </Grid.ColumnDefinitions>
      <TextBlock Grid.Row="0" Grid.Column="0" Text="Task Name:"/>
      <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=TaskName}" />
      <TextBlock Grid.Row="1" Grid.Column="0" Text="Description:"/>
      <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/>
      <TextBlock Grid.Row="2" Grid.Column="0" Text="Priority:"/>
      <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/>
    </Grid>
  </Border>


...


</DataTemplate>

تُظهر اللقطة التالية ListBox مع هذا DataTemplate المعدّل:

لقطة شاشة لعينة من قوالب البيانات

يمكننا تعيين HorizontalContentAlignment إلى Stretch على ListBox للتأكد من أن عرض العناصر يأخذ المساحة بالكامل:

<ListBox Width="400" Margin="10"
     ItemsSource="{Binding Source={StaticResource myTodoList}}"
     ItemTemplate="{StaticResource myTaskTemplate}" 
     HorizontalContentAlignment="Stretch"/>

مع خاصية HorizontalContentAlignment معينة إلى Stretch، يبدو ListBox الآن مثل هذا:

لقطة شاشة لعينة من قوالب البيانات

استخدام DataTriggers لتطبيق قيم الخاصية

العرض التقديمي الحالي لا يعلمنا ما إذا كان Task مهمة منزلية أو مهمة مكتبية. تذكر أن كائن Task يحتوي على خاصية TaskType من نوع TaskType ، و هو تعداد للقيم Home و Work.

في المثال التالي, DataTrigger يعين BorderBrush من العنصر المسمى border إلى Yellow إذا كانت خاصية TaskType هي TaskType.Home.

<DataTemplate x:Key="myTaskTemplate">


...


<DataTemplate.Triggers>
  <DataTrigger Binding="{Binding Path=TaskType}">
    <DataTrigger.Value>
      <local:TaskType>Home</local:TaskType>
    </DataTrigger.Value>
    <Setter TargetName="border" Property="BorderBrush" Value="Yellow"/>
  </DataTrigger>
</DataTemplate.Triggers>


...


</DataTemplate>

التطبيق الخاص بنا الآن يبدو كما يلي. تظهر المهام المنزلية بحد أصفر و تظهر المهام المكتبية بحد توركواز:

لقطة شاشة لعينة من قوالب البيانات

في هذا المثال, DataTrigger يستخدم Setter لتعيين قيمة الخاصية. تتضمن فئات المشغل أيضاً خصائص EnterActions و ExitActions التي تسمح لك ببدء مجموعة من الإجراءات مثل الحركات. بالإضافة إلى ذلك، يوجد أيضاً فئة MultiDataTrigger التي تتيح لك إمكانية تطبيق التغييرات استناداً إلى قيم خاصية ربط البيانات المتعددة.

هناك طريقة بديلة لتحقيق نفس التأثير و هي ربط خاصية BorderBrush إلى خاصية TaskType واستخدام محول القيمة لإرجاع اللون استناداً إلى قيمة TaskType. لمثال مشابه، راجع كيفية القيام بما يلي: تبديل لون الخلفية للصفوف في ListView. إنشاء التأثير أعلاه باستخدام محول أكثر فعالية قليلاً من ناحية الأداء. بالإضافة إلى ذلك، إنشاء المحول الخاص بك يمنحك مرونة أكثر لأنك تقوم بتزويد المنطق الخاص بك. في النهاية، التقنية التي تختارها تعتمد على السيناريو الخاص بك و تفضيلاتك. لمزيد من المعلومات حول كيفية كتابة المحول, راجع IValueConverter.

ما ينتمي إلى DataTemplate؟

في المثال السابق, قمنا بوضع المشغل داخل DataTemplate باستخدام خاصية DataTemplate.Triggers. Setter من المشغل يقوم بتعيين قيمة من خاصية العنصر ( عنصر Border) الذي يقع ضمن DataTemplate. مع ذلك، إذا كانت الخصائص التي يهتم بها Setters الخاص بك ليست خصائص من العناصر ضمن DataTemplate الحالي، قد يكون مناسب أكثر تعيين الخصائص باستخدام Style الذي هو من أجل فئة ListBoxItem (إذا كان عنصر التحكم الذي تقوم بربطه هو ListBox). على سبيل المثال، إذا كنت تريد من Trigger الخاص بك تحريك قيمة Opacity من العنصر عندما يشير الماوس إلى العنصر, قم بتعريف المشغّلات داخل نمط ListBoxItem. لمثال، راجع نموذج مقدمة إلى التنميط و القولبة.

بشكل عام، تذكر أن DataTemplate يتم تطبيقه إلى كل من ListBoxItem الذي تم إنشاؤه (لمزيد من المعلومات حول كيفية و اين تطبيقها فعلياً, راجع صفحة ItemTemplate.). DataTemplate الخاص بك هو مهتم فقط بالعرض التقديمي و مظهر كائنات البيانات. في معظم الحالات، كافة الأوجه الأخرى من العرض التقديمي مثل ما يبدو عليه العنصر عند تحديده أو كيفية إخراج ListBox للعناصر, لا تنتمي في تعريف DataTemplate. للحصول على مثال، راجع مقطع Styling و Templating ItemsControl.

اختيار DataTemplate اعتماداً على الخصائص من كائن البيانات

في مقطع خاصية DataType، تم مناقشة أنك عرفت قوالب البيانات المختلفة لكائنات البيانات المختلفة. يعتبر هذا مفيد بشكل خاص عندما يكون لديك CompositeCollection من أنواع مختلفة أو مجموعات مع عناصر من أنواع مختلفة. في مقطع استخدام DataTriggers لتطبيق قيم الخاصية، وضحنا أنه إذا كان لديك مجموعة من نفس النوع من كائنات البيانات يمكنك إنشاء DataTemplate و ثم استخدام المشغلات لتطبيق التغييرات على أساس قيم الخاصية من كل كائن بيانات. مع ذلك، تسمح المشغّلات لك بتطبيق قيم الخاصية أو بدء حركات لكنها لا تمنحك المرونة لإعادة بناء بنية كائنات البيانات. قد تتطلب بعض السيناريوهات إنشاء DataTemplate مختلفة لكائنات البيانات التي هي من نفس النوع و لكن لديها خصائص مختلفة.

على سبيل المثال، عندما يحتوي كائن Task على قيمة Priority من 1, قد تحتاج إلى إعطائه مظهر مختلف تماماً ليخدم كتنبيه لك. في هذه الحالة، يمكنك إنشاء DataTemplate لعرض كائنات Task ذات الأولوية العالية. دعنا نضيف DataTemplate التالي إلى مقطع الموارد:

<DataTemplate x:Key="importantTaskTemplate">
  <DataTemplate.Resources>
    <Style TargetType="TextBlock">
      <Setter Property="FontSize" Value="20"/>
    </Style>
  </DataTemplate.Resources>
  <Border Name="border" BorderBrush="Red" BorderThickness="1"
          Padding="5" Margin="5">
    <DockPanel HorizontalAlignment="Center">
      <TextBlock Text="{Binding Path=Description}" />
      <TextBlock>!</TextBlock>
    </DockPanel>
  </Border>
</DataTemplate>

لاحظ أن هذا المثال يستخدم خاصية DataTemplate.Resources. الموارد التي تم تعريفها في ذلك المقطع تكون مشتركة من قبل العناصر بداخل DataTemplate.

لتوفير منطق لاختيار أي DataTemplate يجب استخدامه استناداً إلى قيمة Priority من كائن البيانات, قم بإنشاء فئة فرعية من DataTemplateSelector و تجاوز أسلوب SelectTemplate. في المثال التالي, أسلوب SelectTemplate يوفر المنطق لإرجاع القالب المناسب استناداً إلى القيمة من خاصية Priority. القالب المراد إرجاعه يتم العثور عليه في الموارد من عنصر تغليف Window.


Namespace SDKSample
    Public Class TaskListDataTemplateSelector
        Inherits DataTemplateSelector
        Public Overrides Function SelectTemplate(ByVal item As Object, ByVal container As DependencyObject) As DataTemplate
            If item IsNot Nothing AndAlso TypeOf item Is Task Then
                Dim taskitem As Task = TryCast(item, Task)
                Dim window As Window = Application.Current.MainWindow

                If taskitem.Priority = 1 Then
                    Return TryCast(window.FindResource("importantTaskTemplate"), DataTemplate)
                Else
                    Return TryCast(window.FindResource("myTaskTemplate"), DataTemplate)
                End If
            End If

            Return Nothing
        End Function
    End Class
End Namespace
using System.Windows;
using System.Windows.Controls;

namespace SDKSample
{
    public class TaskListDataTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate
            SelectTemplate(object item, DependencyObject container)
        {
            if (item != null && item is Task)
            {
                Task taskitem = item as Task;
                Window window = Application.Current.MainWindow;

                if (taskitem.Priority == 1)
                    return
                        window.FindResource("importantTaskTemplate") as DataTemplate;
                else
                    return
                        window.FindResource("myTaskTemplate") as DataTemplate;
            }

            return null;
        }
    }
}

ثم يمكن تعريف TaskListDataTemplateSelector كمورد:

<Window.Resources>


...


<local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>


...


</Window.Resources>

لاستخدام مورد محدد القالب, قم بتعيينه إلى خاصية ItemTemplateSelector من ListBox. ListBox يستدعي أسلوب SelectTemplate من TaskListDataTemplateSelector لكل من العناصر الموجودة في المجموعة الأساسية. يمرر الاستدعاء كائن البيانات كمعلمة العنصر. DataTemplate التي يتم إرجاعها بواسطة الأسلوب يتم بعد ذلك تطبيقها إلى كائن البيانات.

<ListBox Width="400" Margin="10"
         ItemsSource="{Binding Source={StaticResource myTodoList}}"
         ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
         HorizontalContentAlignment="Stretch"/>

مع وجود محدد القالب في مكانه ، يظهر ListBox الآن كما يلي:

لقطة شاشة لعينة من قوالب البيانات

هذا ينهي المناقشة الخاصة بنا لهذا المثال. للحصول على نموذج كامل, راجع نموذج مقدمة إلى قولبة البيانات.

styling و Templating ItemsControl

بالرغم من أن ItemsControl ليس نوع عنصر التحكم الوحيد الذي يمكنك استخدام DataTemplate معه ، هو سيناريو شائع لربط ItemsControl إلى مجموعة. في مقطع ما ينتمي في DataTemplate قمنا بمناقشة أن تعريف DataTemplate الخاص بك يجب أن يكون مهتم فقط بالعرض التقديمي للبيانات. من أجل أن نعرف عندما يكون غير مناسب استخدام DataTemplate, من المهم فهم النمط المختلف و خصائص القالب التي توفرها ItemsControl. يتم تصميم المثال التالي لتوضيح الدالة لكل من هذه الخصائص. ItemsControl في هذا المثال موثوق‬ إلى نفس مجموعة Tasks كما في المثال السابق. لأغراض العرض التوضيحي لأغراض, الأنماط و القوالب في هذا المثال كلها معرفة ضمنياً.

<ItemsControl Margin="10"
              ItemsSource="{Binding Source={StaticResource myTodoList}}">
  <!--The ItemsControl has no default visual appearance.
      Use the Template property to specify a ControlTemplate to define
      the appearance of an ItemsControl. The ItemsPresenter uses the specified
      ItemsPanelTemplate (see below) to layout the items. If an
      ItemsPanelTemplate is not specified, the default is used. (For ItemsControl,
      the default is an ItemsPanelTemplate that specifies a StackPanel.-->
  <ItemsControl.Template>
    <ControlTemplate TargetType="ItemsControl">
      <Border BorderBrush="Aqua" BorderThickness="1" CornerRadius="15">
        <ItemsPresenter/>
      </Border>
    </ControlTemplate>
  </ItemsControl.Template>
  <!--Use the ItemsPanel property to specify an ItemsPanelTemplate
      that defines the panel that is used to hold the generated items.
      In other words, use this property if you want to affect
      how the items are laid out.-->
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <WrapPanel />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  <!--Use the ItemTemplate to set a DataTemplate to define
      the visualization of the data objects. This DataTemplate
      specifies that each data object appears with the Proriity
      and TaskName on top of a silver ellipse.-->
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <DataTemplate.Resources>
        <Style TargetType="TextBlock">
          <Setter Property="FontSize" Value="18"/>
          <Setter Property="HorizontalAlignment" Value="Center"/>
        </Style>
      </DataTemplate.Resources>
      <Grid>
        <Ellipse Fill="Silver"/>
        <StackPanel>
          <TextBlock Margin="3,3,3,0"
                     Text="{Binding Path=Priority}"/>
          <TextBlock Margin="3,0,3,7"
                     Text="{Binding Path=TaskName}"/>
        </StackPanel>
      </Grid>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
  <!--Use the ItemContainerStyle property to specify the appearance
      of the element that contains the data. This ItemContainerStyle
      gives each item container a margin and a width. There is also
      a trigger that sets a tooltip that shows the description of
      the data object when the mouse hovers over the item container.-->
  <ItemsControl.ItemContainerStyle>
    <Style>
      <Setter Property="Control.Width" Value="100"/>
      <Setter Property="Control.Margin" Value="5"/>
      <Style.Triggers>
        <Trigger Property="Control.IsMouseOver" Value="True">
          <Setter Property="Control.ToolTip"
                  Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                          Path=Content.Description}"/>
        </Trigger>
      </Style.Triggers>
    </Style>
  </ItemsControl.ItemContainerStyle>
</ItemsControl>

التالي هو لقطة من المثال عندما يتم تقديمه:

لقطة شاشة لمثال ItemsControl

لاحظ أنه بدلاً من استخدام ItemTemplate، يمكنك استخدام ItemTemplateSelector. ارجع إلى المقطع السابق للحصول على مثال. بشكل مماثل، بدلاً من استخدام ItemContainerStyle ، يكون لديك الخيار لاستخدام ItemContainerStyleSelector.

اثنين من الخصائص ذات الصلة بالنمط من ItemsControl اللتين لا تظهران هنا هم GroupStyle و GroupStyleSelector.

دعم البيانات ذات التسلسل الهرمي

حتى الآن لقد نظرنا فقط في كيفية الربط إلى مجموعة واحدة و عرضها. أحياناً يكون لديك مجموعة تحتوي على مجموعات أخرى. فئة HierarchicalDataTemplate تم تصميمها لاستخدامها مع أنواع HeaderedItemsControl لعرض مثل هذه البيانات. في المثال التالي, ListLeagueList هو قائمة من كائنات League. كل كائن League يحتوي على Name و مجموعة من كائنات Division. كل Division يحتوي على Name و مجموعة من كائنات Team، و كل كائن Team يحتوي على Name.

<Window x:Class="SDKSample.Window1"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  Title="HierarchicalDataTemplate Sample"
  xmlns:src="clr-namespace:SDKSample">
  <DockPanel>
    <DockPanel.Resources>
      <src:ListLeagueList x:Key="MyList"/>

      <HierarchicalDataTemplate DataType    = "{x:Type src:League}"
                                ItemsSource = "{Binding Path=Divisions}">
        <TextBlock Text="{Binding Path=Name}"/>
      </HierarchicalDataTemplate>

      <HierarchicalDataTemplate DataType    = "{x:Type src:Division}"
                                ItemsSource = "{Binding Path=Teams}">
        <TextBlock Text="{Binding Path=Name}"/>
      </HierarchicalDataTemplate>

      <DataTemplate DataType="{x:Type src:Team}">
        <TextBlock Text="{Binding Path=Name}"/>
      </DataTemplate>
    </DockPanel.Resources>

    <Menu Name="menu1" DockPanel.Dock="Top" Margin="10,10,10,10">
        <MenuItem Header="My Soccer Leagues"
                  ItemsSource="{Binding Source={StaticResource MyList}}" />
    </Menu>

    <TreeView>
      <TreeViewItem ItemsSource="{Binding Source={StaticResource MyList}}" Header="My Soccer Leagues" />
    </TreeView>

  </DockPanel>
</Window>

يوضح المثال أن باستخدام HierarchicalDataTemplate، يمكنك بسهولة عرض بيانات القائمة التي تحتوي على قوائم أخرى. التالي هو لقطة من المثال.

لقطة شاشة لعينة HierarchicalDataTemplate

راجع أيضًا:

المهام

كيفية القيام بما يلي: البحث عن عناصر منشأة من DataTemplate

المبادئ

أمثلية الأداء: ربط البيانات.

التنسيق و القولبة

نظرة عامة لربط البيانات

أنماط عنوان عمود GridView و نظرة عامة حول ‏‫القوالب