İç İçe Veri Web Denetimleri (C#)Nested Data Web Controls (C#)

Scott Mitchell tarafındanby Scott Mitchell

Örnek uygulamayı indirin veya PDF 'yi indirinDownload Sample App or Download PDF

Bu öğreticide, başka bir yineleyici içinde iç içe geçmiş bir yineleyicisi nasıl kullanacağınızı keşfedeceğiz.In this tutorial we will explore how to use a Repeater nested inside another Repeater. Örnek olarak, iç yineleyicisi hem bildirimli hem de programlı olarak nasıl doldurulacağınız gösterilmektedir.The examples will illustrate how to populate the inner Repeater both declaratively and programmatically.

GirişIntroduction

Statik HTML ve veri bağlama sözdiziminin yanı sıra, Şablonlar Web denetimlerini ve kullanıcı denetimlerini de içerebilir.In addition to static HTML and databinding syntax, templates can also include Web controls and User Controls. Bu Web denetimlerine, özelliklerinin bildirime dayalı, veri bağlama söz dizimi aracılığıyla atanması veya uygun sunucu tarafı olay işleyicilerinde program aracılığıyla erişilebilir olması olabilir.These Web controls can have their properties assigned via declarative, databinding syntax, or can be accessed programmatically in the appropriate server-side event handlers.

Bir şablon içindeki denetimleri gömerek, görünüm ve Kullanıcı deneyimi üzerinde özelleştirilebilir ve geliştirilebilir.By embedding controls within a template, the appearance and user experience can be customized and improved upon. Örneğin, GridView denetim öğreticisindeki TemplateFields kullanarak , bir çalışan bir giriş tarihi göstermek üzere TemplateField içinde Takvim denetimi ekleyerek GridView s görüntüsünü özelleştirmeyi gördük. düzenlemede doğrulama denetimleri ekleme ve arabirim ekleme ve veri değişikliği arabirimi öğreticilerini özelleştirme konusunda, doğrulama denetimleri, metin kutuları, Dropdownlists ve diğer Web denetimleri ekleyerek, düzenlemenin ve ekleme arabirimlerinin nasıl özelleştirileceğini gördük.For example, in the Using TemplateFields in the GridView Control tutorial, we saw how to customize the GridView s display by adding a Calendar control in a TemplateField to show an employee s hire date; in the Adding Validation Controls to the Editing and Inserting Interfaces and Customizing the Data Modification Interface tutorials, we saw how to customize the editing and inserting interfaces by adding validation controls, TextBoxes, DropDownLists, and other Web controls.

Şablonlar, diğer veri Web denetimlerini de içerebilir.Templates can also contain other data Web controls. Diğer bir deyişle, şablonları içinde başka bir DataList (veya Repeater veya GridView ya da DetailsView vb.) içeren bir DataList 'i olabilir.That is, we can have a DataList that contains another DataList (or Repeater or GridView or DetailsView, and so on) within its templates. Böyle bir arabirim ile zorluk, ilgili verileri iç veri Web denetimine bağlamadır.The challenge with such an interface is binding the appropriate data to the inner data Web control. Kullanılabilir birkaç farklı yaklaşım vardır ve bunları programlı bir şekilde kullanarak bildirim temelli seçeneklerden farklıdır.There are a few different approaches available, ranging from declarative options using the ObjectDataSource to programmatic ones.

Bu öğreticide, başka bir yineleyici içinde iç içe geçmiş bir yineleyicisi nasıl kullanacağınızı keşfedeceğiz.In this tutorial we will explore how to use a Repeater nested inside another Repeater. Dış Yineleyici, kategori adı ve açıklamasını görüntüleyerek veritabanındaki her bir kategori için bir öğe içerecektir.The outer Repeater will contain an item for each category in the database, displaying the category s name and description. Her bir kategori öğesi iç Yineleyici, bu kategoriye ait her bir ürün için bilgileri (bkz. Şekil 1) madde işaretli bir listede görüntüler.Each category item s inner Repeater will display information for each product belonging to that category (see Figure 1) in a bulleted list. Örneklerimizde iç yineleyicisi hem bildirimli hem de programlı olarak nasıl doldurulacağınız gösterilmektedir.Our examples will illustrate how to populate the inner Repeater both declaratively and programmatically.

Her kategori , ürünleriyle birlikte listelenirEach Category, Along with its Products, are Listed

Şekil 1: her kategori, ürünlerle birlikte listelenir (tam boyutlu görüntüyü görüntülemek için tıklayın)Figure 1: Each Category, Along with its Products, are Listed (Click to view full-size image)

1. Adım: Kategori listesini oluşturmaStep 1: Creating the Category Listing

İç içe geçmiş veri Web denetimlerini kullanan bir sayfa oluştururken, iç içe geçmiş denetim hakkında endişelenmeden önce en dıştaki veri Web denetimini tasarlamak, oluşturmak ve test etmek faydalı olduğunu öğreniyorum.When building a page that uses nested data Web controls, I find it helpful to design, create, and test the outermost data Web control first, without even worrying about the inner nested control. Bu nedenle, her bir kategorinin adını ve açıklamasını listeleyen sayfaya bir yineleyici eklemek için gereken adımları izleyerek başlayalım.Therefore, let s start by walking through the steps necessary to add a Repeater to the page that lists the name and description for each category.

NestedControls.aspx sayfasını DataListRepeaterBasics klasöründen açıp sayfaya bir yineleyici denetimi ekleyerek ID özelliğini CategoryListolarak ayarlayarak başlayın.Start by opening the NestedControls.aspx page in the DataListRepeaterBasics folder and add a Repeater control to the page, setting its ID property to CategoryList. Yineleyici s akıllı etiketinden CategoriesDataSourceadlı yeni bir ObjectDataSource oluşturmayı seçin.From the Repeater s smart tag, choose to create a new ObjectDataSource named CategoriesDataSource.

Yeni ObjectDataSource CategoriesDataSource adıName the New ObjectDataSource CategoriesDataSource

Şekil 2: yeni ObjectDataSource CategoriesDataSource adlandırma (tam boyutlu görüntüyü görüntülemek için tıklayın)Figure 2: Name the New ObjectDataSource CategoriesDataSource (Click to view full-size image)

ObjectDataSource 'ı, verileri CategoriesBLL sınıf s GetCategories yönteminden çeker şekilde yapılandırın.Configure the ObjectDataSource so that it pulls its data from the CategoriesBLL class s GetCategories method.

, ObjectDataSource 'un CategoriesBLL sınıfı s GetCategories metodunu kullanacak şekilde yapılandırılmasıConfigure the ObjectDataSource to Use the CategoriesBLL Class s GetCategories Method

Şekil 3: CategoriesBLL sınıf s GetCategories metodunu (tam boyutlu görüntüyü görüntülemek Için tıklayın) kullanmak üzere ObjectDataSource 'ı yapılandırınFigure 3: Configure the ObjectDataSource to Use the CategoriesBLL Class s GetCategories Method (Click to view full-size image)

Repeater ' ın şablon içeriğini belirtmek için, kaynak görünümüne gitmemiz ve bildirim temelli sözdizimini el ile girmeniz gerekir.To specify the Repeater s template content we need to go to the Source view and manually enter the declarative syntax. Kategori s adını bir <h4> öğesinde ve kategori s açıklamasını bir paragraf öğesinde (<p>) görüntüleyen bir ItemTemplate ekleyin.Add an ItemTemplate that displays the category s name in an <h4> element and the category s description in a paragraph element (<p>). Ayrıca, her kategoriyi yatay bir kuralla ayıralım (<hr>).Furthermore, let s separate each category with a horizontal rule (<hr>). Bu değişiklikleri yaptıktan sonra sayfanız, aşağıdaki gibi yineleyici ve ObjectDataSource için bildirime dayalı sözdizimi içermelidir:After making these changes your page should contain declarative syntax for the Repeater and ObjectDataSource that is similar to the following:

<asp:Repeater ID="CategoryList" DataSourceID="CategoriesDataSource"
    EnableViewState="False" runat="server">
    <ItemTemplate>
        <h4><%# Eval("CategoryName") %></h4>
        <p><%# Eval("Description") %></p>
    </ItemTemplate>
    <SeparatorTemplate>
        <hr />
    </SeparatorTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

Şekil 4 ' te bir tarayıcıdan görüntülendiklerinde ilerleme durumu gösterilmektedir.Figure 4 shows our progress when viewed through a browser.

her kategorinin adı ve açıklaması, yatay bir kuralla ayrılmış olarak listelenirEach Category s Name and Description is Listed, Separated by a Horizontal Rule

Şekil 4: her kategori adı ve açıklaması, yatay bir kuralla ayrılmış olarak listelenir (tam boyutlu görüntüyü görüntülemek için tıklayın)Figure 4: Each Category s Name and Description is Listed, Separated by a Horizontal Rule (Click to view full-size image)

2. Adım: Iç Içe geçmiş ürün yineleyicisi eklemeStep 2: Adding the Nested Product Repeater

Kategori listeleme tamamlandı, bir sonraki göreviniz, uygun kategoriye ait olan ürünlerle ilgili bilgileri görüntüleyen CategoryList s ItemTemplate bir yineleyici eklemektir.With the category listing complete, our next task is to add a Repeater to the CategoryList s ItemTemplate that displays information about those products belonging to the appropriate category. Bu iç Yineleyici için verileri alabildiğimiz birçok yol vardır. Bu, kısa bir süre içinde araştıracağız.There are a number of ways we can retrieve the data for this inner Repeater, two of which we'll explore shortly. Şimdilik, s ItemTemplate``CategoryList Repeater ' ın içindeki ürünleri yalnızca Yineleyici olarak oluşturalım.For now, let s just create the products Repeater within the CategoryList Repeater s ItemTemplate. Özellikle, ürün yineleyicisi 'nin her bir ürünü, ürün adı ve fiyat dahil olmak üzere her bir liste öğesiyle birlikte madde işaretli bir listede görüntülemesine izin verin.Specifically, let s have the product Repeater display each product in a bulleted list with each list item including the product s name and price.

Bu yineleyicisi oluşturmak için, iç yineleyicisi 'nin bildirim temelli sözdizimini ve şablonları CategoryList s ItemTemplateiçine el ile girmemiz gerekir.To create this Repeater we need to manually enter the inner Repeater s declarative syntax and templates into the CategoryList s ItemTemplate. Aşağıdaki biçimlendirmeyi CategoryList Yineleyici ItemTemplateiçine ekleyin:Add the following markup within the CategoryList Repeater s ItemTemplate:

<asp:Repeater ID="ProductsByCategoryList" EnableViewState="False"
    runat="server">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
    <ItemTemplate>
        <li><strong><%# Eval("ProductName") %></strong>
            (<%# Eval("UnitPrice", "{0:C}") %>)</li>
    </ItemTemplate>
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>

3. Adım: kategoriye özgü ürünleri ProductsByCategoryList Repeater 'a bağlamaStep 3: Binding the Category-Specific Products to the ProductsByCategoryList Repeater

Bu noktada sayfayı bir tarayıcı aracılığıyla ziyaret ederseniz, herhangi bir veriyi yineleyicisi 'ne bağlamamız yaptığımız için ekranınızın Şekil 4 ' te olduğu gibi görünmesi gerekir.If you visit the page through a browser at this point, your screen will look the same as in Figure 4 because we ve yet to bind any data to the Repeater. Uygun ürün kayıtlarını elde etmemiz ve bunları yineleyicisi 'ne bağlamak için birkaç yol vardır ve bunlardan bazıları diğerlerinden daha etkilidir.There are a few ways that we can grab the appropriate product records and bind them to the Repeater, some more efficient than others. Buradaki ana zorluk, belirtilen kategori için uygun ürünleri geri almaktır.The main challenge here is getting back the appropriate products for the specified category.

İç Yineleyici denetimine bağlanacak verilere bildirimli olarak CategoryList ItemTemplateRepeater ' daki bir ObjectDataSource aracılığıyla ya da programlı olarak ASP.NET Page s arka plan kod sayfasından erişilebilir.The data to bind to the inner Repeater control can either be accessed declaratively, through an ObjectDataSource in the CategoryList Repeater s ItemTemplate, or programmatically, from the ASP.NET page s code-behind page. Benzer şekilde, bu veriler iç Yineleyici ile iç yineleyicinin DataSourceID özelliği aracılığıyla ya da bildirim temelli veri bağlama söz dizimi aracılığıyla ya da program aracılığıyla CategoryList Yineleyici s ItemDataBound olay işleyicDataBind() DataSource isindeki iç Yineleyici ile başvurularak programlı bir şekilde bağlanabilir.Similarly, this data can be bound to the inner Repeater either declaratively - through the inner Repeater s DataSourceID property or through declarative databinding syntax or programmatically by referencing the inner Repeater in the CategoryList Repeater s ItemDataBound event handler, programmatically setting its DataSource property, and calling its DataBind() method. Bu yaklaşımların her birini keşfedelim.Let s explore each of these approaches.

Bir ObjectDataSource denetimiyle veItemDataBoundolay Işleyicisiyle verilere bildirimli olarak erişmeAccessing the Data Declaratively with an ObjectDataSource Control and theItemDataBoundEvent Handler

Bu öğretici serisi genelinde ObjectDataSource 'u kapsamlı bir şekilde kullandığımızdan, bu örneğe yönelik verilere erişim için en doğal seçenek, ObjectDataSource 'u kontrol etmek için kullanılır.Since we ve used the ObjectDataSource extensively throughout this tutorial series, the most natural choice for accessing data for this example is to stick with the ObjectDataSource. ProductsBLL sınıfında, belirtilen categoryID ait olan ürünler hakkında bilgi döndüren bir GetProductsByCategoryID(categoryID) yöntemi vardır.The ProductsBLL class has a GetProductsByCategoryID(categoryID) method that returns information about those products that belong to the specified categoryID. Bu nedenle, CategoryList Yineleyici ItemTemplate bir ObjectDataSource ekleyebiliyoruz ve bu sınıf s yönteminden verilerine erişecek şekilde yapılandırabiliriz.Therefore, we can add an ObjectDataSource to the CategoryList Repeater s ItemTemplate and configure it to access its data from this class s method.

Ne yazık ki Yineleyici, şablonlarının Tasarım görünümü aracılığıyla düzenlenmesine izin vermez, bu nedenle bu ObjectDataSource denetimi için bildirim temelli sözdizimini el ile eklememiz gerekir.Unfortunately, the Repeater doesn t allow its templates to be edited through the Design view so we need to add the declarative syntax for this ObjectDataSource control by hand. Aşağıdaki sözdizimi, bu yeni ObjectDataSource eklendikten sonra ItemTemplate CategoryList yineleyicisi 'ni gösterir (ProductsByCategoryDataSource):The following syntax shows the CategoryList Repeater s ItemTemplate after adding this new ObjectDataSource (ProductsByCategoryDataSource):

<h4><%# Eval("CategoryName") %></h4>
<p><%# Eval("Description") %></p>
<asp:Repeater ID="ProductsByCategoryList" EnableViewState="False"
        DataSourceID="ProductsByCategoryDataSource" runat="server">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
    <ItemTemplate>
        <li><strong><%# Eval("ProductName") %></strong> -
                sold as <%# Eval("QuantityPerUnit") %> at
                <%# Eval("UnitPrice", "{0:C}") %></li>
    </ItemTemplate>
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="ProductsByCategoryDataSource" runat="server"
           SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
   <SelectParameters>
        <asp:Parameter Name="CategoryID" Type="Int32" />
   </SelectParameters>
</asp:ObjectDataSource>

ObjectDataSource yaklaşımını kullanırken, ProductsByCategoryList Yineleyici s DataSourceID özelliğini ObjectDataSource 'un (ProductsByCategoryDataSource) ID ayarlaması gerekir.When using the ObjectDataSource approach we need to set the ProductsByCategoryList Repeater s DataSourceID property to the ID of the ObjectDataSource (ProductsByCategoryDataSource). Ayrıca, ObjectDataSource 'lerimizin GetProductsByCategoryID(categoryID) yöntemine geçirilecek categoryID değerini belirten bir <asp:Parameter> öğesi olduğuna dikkat edin.Also, notice that our ObjectDataSource has an <asp:Parameter> element that specifies the categoryID value that will be passed into the GetProductsByCategoryID(categoryID) method. Ancak bu değeri nasıl belirttik?But how do we specify this value? İdeal olarak, aşağıdaki gibi, veri bağlama söz dizimini kullanarak <asp:Parameter> öğesinin DefaultValue özelliğini ayarlayabiliriz:Ideally, we d be able to just set the DefaultValue property of the <asp:Parameter> element using databinding syntax, like so:

<asp:Parameter Name="CategoryID" Type="Int32"
     DefaultValue='<%# Eval("CategoryID")' />

Ne yazık ki, veri bağlama söz dizimi yalnızca DataBinding olayına sahip denetimlerde geçerlidir.Unfortunately, databinding syntax is only valid in controls that have a DataBinding event. Parameter sınıfında böyle bir olay yok ve bu nedenle yukarıdaki sözdizimi geçersizdir ve bir çalışma zamanı hatasına neden olur.The Parameter class lacks such an event and therefore the above syntax is illegal and will result in a runtime error.

Bu değeri ayarlamak için, CategoryList Repeater s ItemDataBound olayı için bir olay işleyicisi oluşturuyoruz.To set this value, we need to create an event handler for the CategoryList Repeater s ItemDataBound event. Yineleyicisi 'ne bağlanan her öğe için ItemDataBound olayının bir kez harekete geçirilir.Recall that the ItemDataBound event fires once for each item bound to the Repeater. Bu nedenle, bu olay dış Yineleyici için her tetiklendiğinde, geçerli CategoryID değerini ProductsByCategoryDataSource ObjectDataSource s CategoryID parametresine atayabiliriz.Therefore, each time this event fires for the outer Repeater we can assign the current CategoryID value to the ProductsByCategoryDataSource ObjectDataSource s CategoryID parameter.

Aşağıdaki kodla CategoryList Repeater s ItemDataBound olayı için bir olay işleyicisi oluşturun:Create an event handler for the CategoryList Repeater s ItemDataBound event with the following code:

protected void CategoryList_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.AlternatingItem ||
        e.Item.ItemType == ListItemType.Item)
    {
        // Reference the CategoriesRow object being bound to this RepeaterItem
        Northwind.CategoriesRow category =
            (Northwind.CategoriesRow)((System.Data.DataRowView)e.Item.DataItem).Row;
        // Reference the ProductsByCategoryDataSource ObjectDataSource
        ObjectDataSource ProductsByCategoryDataSource =
            (ObjectDataSource)e.Item.FindControl("ProductsByCategoryDataSource");
        // Set the CategoryID Parameter value
        ProductsByCategoryDataSource.SelectParameters["CategoryID"].DefaultValue =
            category.CategoryID.ToString();
    }
}

Bu olay işleyicisi, üst bilgi, alt bilgi veya ayırıcı öğe yerine bir veri öğesiyle ilgilenmemiz sağlanarak başlar.This event handler starts by ensuring that we re dealing with a data item rather than the header, footer, or separator item. Ardından, geçerli RepeaterItemzaten bağlanan gerçek CategoriesRow örneğine başvuruyoruz.Next, we reference the actual CategoriesRow instance that has just been bound to the current RepeaterItem. Son olarak, ItemTemplate ObjectDataSource 'a başvurduk ve CategoryID parametre değerini geçerli RepeaterItem``CategoryID atamalısınız.Finally, we reference the ObjectDataSource in the ItemTemplate and assign its CategoryID parameter value to the CategoryID of the current RepeaterItem.

Bu olay işleyicisiyle, her RepeaterItem ProductsByCategoryList yineleyicisi RepeaterItem s kategorisindeki bu ürünlere bağlanır.With this event handler, the ProductsByCategoryList Repeater in each RepeaterItem is bound to those products in the RepeaterItem s category. Şekil 5 elde edilen çıktının ekran görüntüsünü gösterir.Figure 5 shows a screen shot of the resulting output.

Dış Yineleyici her kategoriyi listeler; Inner bir kategori için ürünleri listelerThe Outer Repeater Lists Each Category; the Inner One Lists the Products for that Category

Şekil 5: dış Yineleyici her kategoriyi listeler; Inner bir kategori için ürünleri listeler (tam boyutlu görüntüyü görüntülemek Için tıklayın)Figure 5: The Outer Repeater Lists Each Category; the Inner One Lists the Products for that Category (Click to view full-size image)

Program aracılığıyla kategoriye göre ürünlere erişmeAccessing the Products by Category Data Programmatically

Geçerli kategori için ürünleri almak üzere bir ObjectDataSource kullanmak yerine, bir CategoryIDgeçirildiğinde uygun ürün kümesini döndüren ASP.NET Page s arka plan kod sınıfında (veya App_Code klasöründe veya ayrı bir sınıf kitaplığı projesinde) bir yöntem oluşturarız.Instead of using an ObjectDataSource to retrieve the products for the current category, we could create a method in our ASP.NET page s code-behind class (or in the App_Code folder or in a separate Class Library project) that returns the appropriate set of products when passed in a CategoryID. ASP.NET Page s kod arkasında bir yöntem olduğunu ve GetProductsInCategory(categoryID)adlandırdığını düşünün.Imagine that we had such a method in our ASP.NET page s code-behind class and that it was named GetProductsInCategory(categoryID). Bu yöntemle birlikte, aşağıdaki bildirime dayalı sözdizimini kullanarak geçerli kategorinin ürünlerini iç Yineleyici olarak bağlayabiliriz:With this method in place we could bind the products for the current category to the inner Repeater using the following declarative syntax:

<asp:Repeater runat="server" ID="ProductsByCategoryList" EnableViewState="False"
      DataSource='<%# GetProductsInCategory((int)(Eval("CategoryID"))) %>'>
  ...
</asp:Repeater>

Repeater s DataSource özelliği, verilerinin GetProductsInCategory(categoryID) yönteminden geldiğini göstermek için DataBinding sözdizimini kullanır.The Repeater s DataSource property uses the databinding syntax to indicate that its data comes from the GetProductsInCategory(categoryID) method. Eval("CategoryID") Objecttüründe bir değer döndürdüğünden, nesneyi GetProductsInCategory(categoryID) yöntemine geçirmeden önce bir Integer hale getiririz.Since Eval("CategoryID") returns a value of type Object, we cast the object to an Integer before passing it into the GetProductsInCategory(categoryID) method. Veri bağlama söz dizimi aracılığıyla buraya erişildiğine CategoryID, bu, Categories tablosundaki kayıtlarla bağlantılı olan dış yineleyici (CategoryList) CategoryID.Note that the CategoryID accessed here via the databinding syntax is the CategoryID in the outer Repeater (CategoryList), the one that s bound to the records in the Categories table. Bu nedenle CategoryID bir veritabanı NULL değeri olmadığını biliyoruz. Bu, neden bir DBNullile ilgilendiğinizi kontrol etmeden Eval metodunu daha da düzenleyebilir.Therefore, we know that CategoryID cannot be a database NULL value, which is why we can blindly cast the Eval method without checking if we re dealing with a DBNull.

Bu yaklaşımda GetProductsInCategory(categoryID) yöntemi oluşturuyoruz ve sağlanan categoryID verilen uygun ürün kümesini almamız gerekir.With this approach, we need to create the GetProductsInCategory(categoryID) method and have it retrieve the appropriate set of products given the supplied categoryID. Bunu, ProductsBLL sınıfı s GetProductsByCategoryID(categoryID) metodu tarafından döndürülen ProductsDataTable döndürerek yapabiliriz.We can do this by simply returning the ProductsDataTable returned by the ProductsBLL class s GetProductsByCategoryID(categoryID) method. NestedControls.aspx sayfamız için arka plan kod sınıfında GetProductsInCategory(categoryID) yöntemi oluşturalım.Let s create the GetProductsInCategory(categoryID) method in the code-behind class for our NestedControls.aspx page. Aşağıdaki kodu kullanarak bunu yapın:Do so using the following code:

protected Northwind.ProductsDataTable GetProductsInCategory(int categoryID)
{
    // Create an instance of the ProductsBLL class
    ProductsBLL productAPI = new ProductsBLL();
    // Return the products in the category
    return productAPI.GetProductsByCategoryID(categoryID);
}

Bu yöntem, yalnızca ProductsBLL yönteminin bir örneğini oluşturur ve GetProductsByCategoryID(categoryID) yönteminin sonuçlarını döndürür.This method simply creates an instance of the ProductsBLL method and returns the results of the GetProductsByCategoryID(categoryID) method. Metodun Public veya Protectedolarak işaretlenmesi gerektiğini unutmayın. Yöntem Privateişaretlenmişse, ASP.NET sayfa s bildirime dayalı biçimlendirmeden erişilebilir olmayacaktır.Note that the method must be marked Public or Protected; if the method is marked Private, it will not be accessible from the ASP.NET page s declarative markup.

Bu yeni tekniği kullanmak için bu değişiklikleri yaptıktan sonra, sayfayı bir tarayıcıdan görüntülemek için bir dakikanızı ayırın.After making these changes to use this new technique, take a moment to view the page through a browser. ObjectDataSource ve ItemDataBound olay işleyicisi yaklaşımı kullanılırken çıkış ile aynı olmalıdır (ekran görüntüsünü görmek için Şekil 5 ' e geri dönün).The output should be identical to the output when using the ObjectDataSource and ItemDataBound event handler approach (refer back to Figure 5 to see a screen shot).

Note

ASP.NET Page s arka plan kod sınıfında GetProductsInCategory(categoryID) yöntemi oluşturmak için Busi işi gibi görünebilir.It may seem like busywork to create the GetProductsInCategory(categoryID) method in the ASP.NET page s code-behind class. All, bu yöntem ProductsBLL sınıfının bir örneğini oluşturur ve GetProductsByCategoryID(categoryID) yönteminin sonuçlarını döndürür.After all, this method simply creates an instance of the ProductsBLL class and returns the results of its GetProductsByCategoryID(categoryID) method. Bu yöntemi neden yalnızca iç Yineleyici içindeki veri bağlama sözdiziminden (DataSource='<%# ProductsBLL.GetProductsByCategoryID((int)(Eval("CategoryID"))) %>'gibi) doğrudan çağıramadınız.Why not just call this method directly from the databinding syntax in the inner Repeater, like: DataSource='<%# ProductsBLL.GetProductsByCategoryID((int)(Eval("CategoryID"))) %>'? Bu söz dizimi, ProductsBLL sınıfının geçerli uygulamamız ile çalışmasa da (GetProductsByCategoryID(categoryID) yöntemi bir örnek yöntemi olduğundan), ProductsBLL statik bir GetProductsByCategoryID(categoryID) metodu içerecek şekilde değiştirebilir veya Instance() sınıfının yeni bir örneğini döndürmek için sınıfın statik ProductsBLL yöntemini içermesini sağlayabilirsiniz.Although this syntax won't work with our current implementation of the ProductsBLL class (since the GetProductsByCategoryID(categoryID) method is an instance method), you could modify ProductsBLL to include a static GetProductsByCategoryID(categoryID) method or have the class include a static Instance() method to return a new instance of the ProductsBLL class.

Bu değişiklikler, ASP.NET sayfa kodu arka plan kodundaki GetProductsInCategory(categoryID) yöntemi gereksinimini ortadan kaldıracak, ancak arka plan kod sınıfı yöntemi, kısa süre içinde göreceğiniz şekilde, alınan verilerle çalışma konusunda daha fazla esneklik sağlar.While such modifications would eliminate the need for the GetProductsInCategory(categoryID) method in the ASP.NET page s code-behind class, the code-behind class method gives us more flexibility in working with the data retrieved, as we'll see shortly.

Tüm ürün bilgilerini aynı anda almaRetrieving All of the Product Information at Once

ProductsBLL sınıf s GetProductsByCategoryID(categoryID) yöntemine bir çağrı yaparak inceliyoruz ve bu ürünlerin geçerli kategori için bu ürünleri elde ettiğimiz iki performans tekniği (ilk yaklaşım bir ObjectDataSource tarafından, ikinciden kod arkasındaki GetProductsInCategory(categoryID) yöntemi aracılığıyla).The two pervious techniques we ve examined grab those products for the current category by making a call to the ProductsBLL class s GetProductsByCategoryID(categoryID) method (the first approach did so through an ObjectDataSource, the second through the GetProductsInCategory(categoryID) method in the code-behind class). Bu yöntemin her çağrılışında Iş mantığı katmanı, CategoryID alanı sağlanan giriş parametresiyle eşleşen Products tablosundan satırları döndüren bir SQL ifadesiyle veritabanını sorgulayan veri erişim katmanına geri döner.Each time this method is invoked, the Business Logic Layer calls down to the Data Access Layer, which queries the database with a SQL statement that returns rows from the Products table whose CategoryID field matches the supplied input parameter.

Sistemde bu yaklaşım, tüm kategorileri almak için tek bir veritabanı sorgusuna yönelik n + 1 çağrıları ve her kategoriye özgü ürünleri almak için n çağrısı sağlar.Given N categories in the system, this approach nets N + 1 calls to the database one database query to get all of the categories and then N calls to get the products specific to each category. Ancak, tüm gerekli verileri yalnızca iki veritabanında alabilir ve tüm ürünlerin tümünü almak için bir çağrı yapın.We can, however, retrieve all the needed data in just two database calls one call to get all of the categories and another to get all of the products. Tüm ürünleri edindikten sonra, bu ürünleri yalnızca geçerli CategoryID eşleşen ürünlerin bu kategoriye ait iç Yineleyici ile bağlanacağı şekilde filtreleyebiliriz.Once we have all of the products, we can filter those products so that only the products matching the current CategoryID are bound to that category s inner Repeater.

Bu işlevi sağlamak için, ASP.NET Page s Code-Behind sınıfındaki GetProductsInCategory(categoryID) yönteminde yalnızca küçük bir değişiklik yapmanız gerekir.To provide this functionality, we only need to make a slight modification to the GetProductsInCategory(categoryID) method in our ASP.NET page s code-behind class. ProductsBLL sınıf s GetProductsByCategoryID(categoryID) yönteminin sonuçlarını bir adım adım geri döndürmek yerine, bu ürünlerin tümüne ilk kez erişebiliriz (önceden erişilmemişse) ve ardından, geçirilen CategoryIDgöre yalnızca ürünlerin filtrelenmiş görünümünü geri alabilirsiniz.Rather than blindly returning the results of the ProductsBLL class s GetProductsByCategoryID(categoryID) method, we can instead first access all of the products (if they haven't been accessed already) and then return just the filtered view of the products based on the passed-in CategoryID.

private Northwind.ProductsDataTable allProducts = null;
protected Northwind.ProductsDataTable GetProductsInCategory(int categoryID)
{
    // First, see if we've yet to have accessed all of the product information
    if (allProducts == null)
    {
        ProductsBLL productAPI = new ProductsBLL();
        allProducts = productAPI.GetProducts();
    }
    // Return the filtered view
    allProducts.DefaultView.RowFilter = "CategoryID = " + categoryID;
    return allProducts;
}

Sayfa düzeyi değişkeninin eklenmesini allProducts.Note the addition of the page-level variable, allProducts. Bu, tüm ürünlerle ilgili bilgileri barındırır ve GetProductsInCategory(categoryID) yöntemi ilk kez çağrıldığında doldurulur.This holds information about all of the products and is populated the first time the GetProductsInCategory(categoryID) method is invoked. allProducts nesnesinin oluşturulup doldurulduğundan emin olduktan sonra, yöntemi DataTable s sonuçlarını yalnızca CategoryID belirtilen CategoryID eşleşen satırlara erişilebilir olacak şekilde filtreler.After ensuring that the allProducts object has been created and populated, the method filters the DataTable s results such that only those rows whose CategoryID matches the specified CategoryID are accessible. Bu yaklaşım, veritabanına N + 1 ' den iki kez erişilme sayısını azaltır.This approach reduces the number of times the database is accessed from N + 1 down to two.

Bu geliştirme, sayfanın işlenmiş biçimlendirmesinde herhangi bir değişikliğe neden olmaz, ne de diğer yaklaşımdan daha az kayıt geri getirir.This enhancement does not introduce any change to the rendered markup of the page, nor does it bring back fewer records than the other approach. Yalnızca veritabanına yapılan çağrıların sayısını azaltır.It simply reduces the number of calls to the database.

Note

Bunlardan biri, veritabanı erişimlerini azaltmak assuredly performansı artırmak için çok sayıda neden olabilir.One might intuitively reason that reducing the number of database accesses would assuredly improve performance. Ancak, bu durum olmayabilir.However, this might not be the case. CategoryID NULLolan çok sayıda ürünsahipseniz, örneğin GetProducts yöntemine yapılan çağrı, hiçbir şekilde görüntülenmeyen bir dizi ürünü geri döndürür.If you have a large number of products whose CategoryID is NULL, for example, then the call to the GetProducts method returns a number of products that are never displayed. Üstelik, yalnızca kategorilerin bir alt kümesini gösteriyorsanız, bu, sayfalama uygulamış olmanız durumunda olabilecek tüm ürünlerin döndürülmesi beklenebilir.Moreover, returning all of the products can be wasteful if you re only showing a subset of the categories, which might be the case if you have implemented paging.

Her zaman olduğu gibi, iki tekninin performansını analiz etmek için tek SureFire ölçüsü, uygulamanızın ortak olay senaryolarınız için uyarlanmış denetimli testleri çalıştırmalıdır.As always, when it comes to analyzing the performance of two techniques, the only surefire measure is to run controlled tests tailored for your application s common case scenarios.

ÖzetSummary

Bu öğreticide, bir veri Web denetiminin başka bir şekilde nasıl iç yineleyicisi olduğunu, özellikle de bir dış yineleyicisi 'nin bir madde işaretli liste içindeki her bir kategorinin ürünlerini listeleme iç Yineleyici olan her kategori için bir öğe göstermesini gördük.In this tutorial we saw how to nest one data Web control within another, specifically examining how to have an outer Repeater display an item for each category with an inner Repeater listing the products for each category in a bulleted list. İç içe bir kullanıcı arabirimi oluşturmanın ana zorluğu, doğru verileri iç veri Web denetimine bağlama ve bunlara bağlama konusunda yer alır.The main challenge in building a nested user interface lies in accessing and binding the correct data to the inner data Web control. Bu öğreticide incelenen, iki farklı teknik mevcuttur.There are a variety of techniques available, two of which we examined in this tutorial. İlk yaklaşım, DataSourceID özelliği aracılığıyla iç veri Web denetimine bağlanan ItemTemplate dış veri Web denetimindeki bir ObjectDataSource kullandı.The first approach examined used an ObjectDataSource in the outer data Web control s ItemTemplate that was bound to the inner data Web control through its DataSourceID property. İkinci teknikte, ASP.NET Page s arka plan kod sınıfındaki bir yöntem aracılığıyla verilere erişilir.The second technique accessed the data via a method in the ASP.NET page s code-behind class. Bu yöntem daha sonra veri bağlama söz dizimi aracılığıyla iç veri Web denetimi s DataSource özelliğine bağlanabilir.This method can then be bound to the inner data Web control s DataSource property through databinding syntax.

Bu öğreticide incelenen iç içe geçmiş kullanıcı arabirimi, bir yineleyici içinde iç içe geçmiş bir yineleyici kullanıyordu, bu teknikler diğer veri Web denetimlerine genişletilebilir.While the nested user interface examined in this tutorial used a Repeater nested within a Repeater, these techniques can be extended to the other data Web controls. Bir ya da bir GridView içinde bir bir yineleyici iç içe veya bir GridView içinde bir GridView oluşturabilirsiniz.You can nest a Repeater within a GridView, or a GridView within a DataList, and so on.

Programlamanın kutlu olsun!Happy Programming!

Yazar hakkındaAbout the Author

4GuysFromRolla.com 'in, Scott Mitchell, yedi ASP/ASP. net books ve 'in yazarı, 1998 sürümünden bu yana Microsoft Web teknolojileriyle çalışmaktadır.Scott Mitchell, author of seven ASP/ASP.NET books and founder of 4GuysFromRolla.com, has been working with Microsoft Web technologies since 1998. Scott bağımsız danışman, Trainer ve yazıcı olarak çalışıyor.Scott works as an independent consultant, trainer, and writer. En son kitabı, 24 saat içinde ASP.NET 2,0 kendi kendinize eğitimister.His latest book is Sams Teach Yourself ASP.NET 2.0 in 24 Hours. mitchell@4GuysFromRolla.comadresinden erişilebilir .He can be reached at mitchell@4GuysFromRolla.com. ya da blog aracılığıyla http://ScottOnWriting.NETbulabilirsiniz.or via his blog, which can be found at http://ScottOnWriting.NET.

Özel olarak teşekkürlerSpecial Thanks To

Bu öğretici serisi birçok yararlı gözden geçirenler tarafından incelendi.This tutorial series was reviewed by many helpful reviewers. Bu öğreticide lider gözden geçirenler Zack Jones ve Liz Shulok.Lead reviewers for this tutorial were Zack Jones and Liz Shulok. Yaklaşan MSDN makalelerimi gözden geçiriyor musunuz?Interested in reviewing my upcoming MSDN articles? Öyleyse, benimitchell@4GuysFromRolla.combir satır bırakın .If so, drop me a line at mitchell@4GuysFromRolla.com.