İç İçe Veri Web Denetimleri (C#)

tarafından Scott Mitchell

PDF’yi İndir

Bu öğreticide, başka bir Repeater içinde iç içe yerleştirilmiş bir Repeater'ın nasıl kullanılacağını keşfedeceğiz. Örnekler, iç Repeater'ın bildirim temelli ve programlı olarak nasıl doldurulacağını gösterir.

Giriş

Şablonlar, statik HTML ve veri bağlama söz dizimine ek olarak Web denetimleri ve Kullanıcı Denetimleri de içerebilir. Bu Web denetimlerinin özellikleri bildirim temelli, veri bağlama söz dizimi aracılığıyla atanabilir veya uygun sunucu tarafı olay işleyicilerinde program aracılığıyla erişilebilir.

Denetimleri bir şablona ekleyerek görünüm ve kullanıcı deneyimi özelleştirilebilir ve geliştirilebilir. Örneğin, GridView Denetimi öğreticisindeki TemplateFields kullanma öğreticisinde , bir çalışanın işe alma tarihini göstermek için TemplateField'e takvim denetimi ekleyerek GridView görünümünü özelleştirmeyi gördük; Düzenleme ve Ekleme Arabirimlerine Doğrulama Denetimleri Ekleme veVeri Değiştirme Arabirimini Özelleştirme öğreticilerinde doğrulama denetimleri, TextBoxes, DropDownLists ve diğer Web denetimleri ekleyerek arabirimleri düzenlemeyi ve eklemeyi gördük.

Şablonlar başka veri Web denetimleri de içerebilir. Başka bir ifadeyle, şablonlarında başka bir DataList (veya Repeater, GridView veya DetailsView vb.) içeren bir DataList'imiz olabilir. Böyle bir arabirimle ilgili zorluk, uygun verileri iç veri Web denetimine bağlamaktır. ObjectDataSource'un kullanıldığı bildirim temelli seçeneklerden programlama seçeneklerine kadar birkaç farklı yaklaşım vardır.

Bu öğreticide, başka bir Repeater içinde iç içe yerleştirilmiş bir Repeater'ın nasıl kullanılacağını keşfedeceğiz. Dış Repeater, veritabanındaki her kategori için kategorinin adını ve açıklamasını görüntüleyen bir öğe içerir. Her kategori öğesinin iç Yineleyicisi, madde işaretli bir listede söz konusu kategoriye ait her ürünün bilgilerini görüntüler (bkz. Şekil 1). Örneklerimizde iç Repeater'ın bildirim temelli ve programlı olarak nasıl doldurulacağı gösterilmektedir.

Her Kategori, Ürünleriyle Birlikte Listelenir

Şekil 1: Her Kategori, Ürünleriyle Birlikte Listelenir (Tam boyutlu görüntüyü görüntülemek için tıklayın)

1. Adım: Kategori Listesini Oluşturma

İç içe veri Web denetimlerini kullanan bir sayfa oluştururken, iç içe geçmiş denetim konusunda endişelenmeden en dıştaki veri Web denetimini tasarlamayı, oluşturmayı ve test etmeye yardımcı olur. Bu nedenle, her kategorinin adını ve açıklamasını listeleyen sayfaya bir Repeater eklemek için gereken adımları izleyerek başlayalım.

İlk olarak klasördeki DataListRepeaterBasics sayfayı NestedControls.aspx açın ve özelliği olarak ayarlayarak IDCategoryListsayfaya bir Repeater denetimi ekleyin. Repeater'ın akıllı etiketinden adlı CategoriesDataSourceyeni bir ObjectDataSource oluşturmayı seçin.

Yeni ObjectDataSource KategorileriniDataSource Olarak Adlandırın

Şekil 2: Yeni ObjectDataSource CategoriesDataSource adını verin (tam boyutlu görüntüyü görüntülemek için tıklayın)

ObjectDataSource'ı, sınıfın GetCategories yönteminden CategoriesBLL verilerini çekecek şekilde yapılandırın.

ObjectDataSource'ı CategoriesBLL Sınıfının GetCategories Yöntemini Kullanacak Şekilde Yapılandırma

Şekil 3: ObjectDataSource'ı GetCategories Sınıf Yöntemini Kullanacak CategoriesBLL Şekilde Yapılandırma (Tam boyutlu görüntüyü görüntülemek için tıklayın)

Repeater şablonu içeriğini belirtmek için Kaynak görünümüne gidip bildirim temelli söz dizimini el ile girmemiz gerekir. Bir ItemTemplate öğede kategori adını ve paragraf <h4> öğesinde (<p>) kategori açıklamasını görüntüleyen bir ekleyin. Ayrıca, her kategoriyi yatay bir kuralla (<hr> ) ayıralım. Bu değişiklikleri yaptıktan sonra sayfanız Repeater ve ObjectDataSource için aşağıdakine benzer bildirim temelli söz dizimi içermelidir:

<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'de tarayıcı üzerinden görüntülendiğinde ilerleme durumumuz gösterilmektedir.

Her Kategorinin Adı ve Açıklaması Yatay Kuralla Ayrılmış Olarak Listelenir

Şekil 4: Her Kategorinin Adı ve Açıklaması Yatay Kuralla Ayrılmış Olarak Listelenir (Tam boyutlu resmi görüntülemek için tıklayın)

2. Adım: İç İçe Ürün Yineleyicisini Ekleme

Kategori listesi tamamlandıktan sonra, sonraki görevimiz, uygun kategoriye CategoryList ait ürünlerle ilgili bilgileri görüntüleyen bir ItemTemplate Repeater eklemektir. Bu iç Repeater'ın verilerini almanın birkaç yolu vardır; bunlardan ikisini kısa süre içinde inceleyeceğiz. Şimdilik Repeater'ın ItemTemplateiçinde CategoryList repeater ürünlerini oluşturalım. Özellikle, Repeater ürününün her ürünü, ürün adı ve fiyatı dahil olmak üzere her liste öğesiyle birlikte madde işaretli bir listede görüntülemesini sağlayın.

Bu Repeater'ı oluşturmak için iç Repeater'ın bildirim temelli söz dizimini ve şablonlarını s ItemTemplateiçine CategoryList el ile girmemiz gerekir. Repeater'ın ItemTemplateiçine aşağıdaki işaretlemeyi CategoryList ekleyin:

<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: Category-Specific Ürünlerini ProductsByCategoryList Repeater'a Bağlama

Bu noktada sayfayı bir tarayıcı üzerinden ziyaret ederseniz, yineleyiciye herhangi bir veri bağlamadığımız için ekranınız Şekil 4'tekiyle aynı görünür. Uygun ürün kayıtlarını alıp Repeater'a bağlamanın birkaç yolu vardır; bazıları diğerlerinden daha verimlidir. Buradaki temel zorluk, belirtilen kategori için uygun ürünleri geri almaktır.

İç Repeater denetimine bağlanacak verilere, Repeater'ın ItemTemplateiçindeki bir ObjectDataSource CategoryList aracılığıyla veya program aracılığıyla, ASP.NET sayfasının arka kod arkası sayfasından bildirim temelli olarak erişilebilir. Benzer şekilde, bu veriler iç Repeater'ın özelliği aracılığıyla veya bildirim temelli veri bağlama söz dizimi aracılığıyla veya Repeater'ın DataSourceID olay işleyicisindeki CategoryList iç Repeater'a başvurarak, özelliğini program aracılığıyla ayarlayarak DataSource ve yöntemini çağırarak DataBind() iç Repeater'a ItemDataBound bağlanabilir. Şimdi bu yaklaşımların her birini inceleyelim.

ObjectDataSource Denetimi veItemDataBoundOlay İşleyicisi ile Verilere Bildirimli Olarak Erişme

Bu öğretici serisi boyunca ObjectDataSource'ı yoğun bir şekilde kullandığımızdan, bu örnekteki verilere erişmek için en doğal seçenek ObjectDataSource'a bağlı kalmaktır. sınıfı, ProductsBLL belirtilen categoryIDöğesine ait olan ürünler hakkında bilgi döndüren bir GetProductsByCategoryID(categoryID) yönteme sahiptir. Bu nedenle, Repeater'a ItemTemplate bir ObjectDataSource ekleyebilir ve bu sınıfın CategoryList yönteminden verilerine erişmek için yapılandırabiliriz.

Ne yazık ki Repeater ş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öz dizimini el ile eklememiz gerekir. Aşağıdaki söz dizimi, bu yeni ObjectDataSource (ProductsByCategoryDataSource) eklendikten sonra Repeater'ları ItemTemplate gösterirCategoryList:

<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 Repeater s DataSourceID özelliğini ObjectDataSource ()ProductsByCategoryDataSource olarak ID ayarlamamız ProductsByCategoryList gerekir. Ayrıca, ObjectDataSource'umuzun yöntemine categoryIDGetProductsByCategoryID(categoryID) geçirilecek değeri belirten bir <asp:Parameter> öğesine sahip olduğuna dikkat edin. Peki bu değeri nasıl belirteceğiz? İdeal olarak, veri bağlama söz dizimini DefaultValue kullanarak öğesinin <asp:Parameter> özelliğini ayarlayabiliriz, örneğin:

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

Ne yazık ki, veri bağlama söz dizimi yalnızca olay DataBinding içeren denetimlerde geçerlidir. Sınıfında Parameter böyle bir olay olmadığından yukarıdaki söz dizimi geçersizdir ve çalışma zamanı hatasına neden olur.

Bu değeri ayarlamak için Repeater ItemDataBound olayı için bir olay işleyicisi CategoryList oluşturmamız gerekir. Olayın Repeater'a ItemDataBound bağlı her öğe için bir kez tetiklendiğini hatırlayın. Bu nedenle, bu olay dış Repeater için her tetiklendiğinde geçerli CategoryID değeri ObjectDataSource CategoryID parametresine ProductsByCategoryDataSource atayabiliriz.

Repeater ItemDataBound olayı için CategoryList aşağıdaki kodla bir olay işleyicisi oluşturun:

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 ilgilendiğimizden emin olarak başlar. Ardından, geçerli RepeaterItemöğesine bağlı olan gerçek CategoriesRow örneğe başvuracağız. Son olarak, içinde ObjectDataSource'a ItemTemplateCategoryID başvuruyoruz ve parametre değerini geçerli RepeaterItemöğesine atıyoruzCategoryID.

Bu olay işleyicisiyle, ProductsByCategoryList her RepeaterItem birindeki Repeater, s kategorisindeki RepeaterItem ürünlere bağlıdır. Şekil 5'de sonuçta elde edilen çıkışın ekran görüntüsü gösterilir.

Dış Yineleyici Her Kategoriyi Listeler; İç Yineleme söz Listeler Bu Kategori için Ürünler

Şekil 5: Dış Yineleyici Her Kategoriyi Listeler; İç Olan, Bu Kategorinin Ürünleri Listeler (Tam boyutlu görüntüyü görüntülemek için tıklayın)

Kategori Verilerine Göre Ürünlere Program Aracılığıyla Erişme

Geçerli kategoriye ait ürünleri almak için ObjectDataSource kullanmak yerine, ASP.NET sayfamızın arka planda kod sınıfında (veya klasöründe veya App_Code ayrı bir Sınıf Kitaplığı projesinde) içinde geçirildiğinde uygun ürün kümesini döndüren bir CategoryIDyöntem oluşturabiliriz. ASP.NET sayfamızın code-behind sınıfında böyle bir yöntemimiz olduğunu ve olarak adlandırıldığını GetProductsInCategory(categoryID)düşünün. Bu yöntem kullanıldığında, aşağıdaki bildirim temelli söz dizimini kullanarak geçerli kategoriye ilişkin ürünleri iç Repeater'a bağlayabiliriz:

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

Repeater özelliği DataSource , verilerinin yönteminden geldiğini belirtmek için veri bağlama söz dizimini GetProductsInCategory(categoryID) kullanır. türünde Objectbir değer döndürdüğündenEval("CategoryID"), yöntemine geçirmeden önce nesnesini bir Integer değerine GetProductsInCategory(categoryID) atarız. CategoryID Burada veri bağlama söz dizimi aracılığıyla erişilen değerinCategoryID, tablodaki kayıtlara bağlı olan dış Repeater()CategoryList öğesi Categories olduğunu unutmayın. Bu nedenle, bir veritabanı değeri olamayacağını CategoryID biliyoruz, bu nedenle bir ile DBNullilgilenip ilgilenmediğimize denetlemeden yöntemini körü körüne yayınlayabilirizEval.NULL

Bu yaklaşımla yöntemini oluşturmamız GetProductsInCategory(categoryID) ve sağlanan categoryIDverilen uygun ürün kümesini almasını sağlamalıyız. Bunu yalnızca sınıfın ProductsDataTableGetProductsByCategoryID(categoryID) yöntemi tarafından döndürülen döndürerek ProductsBLL yapabiliriz. Şimdi sayfamızın NestedControls.aspx arka planda kod sınıfında yöntemini oluşturalımGetProductsInCategory(categoryID). Bunu aşağıdaki kodu kullanarak yapın:

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 basitçe yönteminin bir örneğini ProductsBLL oluşturur ve yönteminin GetProductsByCategoryID(categoryID) sonuçlarını döndürür. yönteminin veya Protectedolarak işaretlenmesi Public gerektiğini unutmayın; yöntem işaretlenmişsePrivate, ASP.NET sayfasının bildirim temelli işaretlemesinden erişilemez.

Bu yeni tekniği kullanmak için bu değişiklikleri yaptıktan sonra, sayfayı bir tarayıcı üzerinden görüntülemek için biraz zaman ayırın. ObjectDataSource ve ItemDataBound olay işleyicisi yaklaşımı kullanılırken çıkış, çıkışla aynı olmalıdır (ekran görüntüsünü görmek için Şekil 5'e geri bakın).

Not

ASP.NET sayfasının arka planda kod sınıfında yöntemini oluşturmak GetProductsInCategory(categoryID) meşgul gibi görünebilir. Sonuçta, bu yöntem yalnızca sınıfının bir örneğini ProductsBLL oluşturur ve yönteminin GetProductsByCategoryID(categoryID) sonuçlarını döndürür. Neden bu yöntemi doğrudan iç Repeater'daki veri bağlama söz diziminden çağırmıyor, örneğin: DataSource='<%# ProductsBLL.GetProductsByCategoryID((int)(Eval("CategoryID"))) %>'? Bu söz dizimi geçerli sınıf uygulamamızla ProductsBLL çalışmasa da (yöntem bir örnek yöntemi olduğundanGetProductsByCategoryID(categoryID)), statik GetProductsByCategoryID(categoryID) bir yöntem içerecek şekilde değiştirebilir ProductsBLL veya sınıfın yeni bir sınıfın örneğini döndürmek için statik Instance() bir yöntem içermesini ProductsBLL sağlayabilirsiniz.

Bu tür değişiklikler ASP.NET sayfasının arka kod arkası sınıfında yönteminin gereksinimini GetProductsInCategory(categoryID) ortadan kaldırsa da arka planda kod yöntemi, kısa süre içinde göreceğimiz gibi alınan verilerle çalışma konusunda bize daha fazla esneklik sağlar.

Tüm Ürün Bilgilerini Aynı Anda Alma

İncelediğimiz iki pervious teknik, sınıfın GetProductsByCategoryID(categoryID) yöntemine ProductsBLL bir çağrı yaparak geçerli kategori için bu ürünleri alır (ilk yaklaşım bunu ObjectDataSource aracılığıyla, ikinci yaklaşım ise arka kod arkası sınıfındaki GetProductsInCategory(categoryID) yöntemi aracılığıyla yapmıştır). Bu yöntem her çağrıldığında İş Mantığı Katmanı Veri Erişim Katmanı'nı çağırır. Bu katman, alanı sağlanan giriş parametresiyle eşleşen tablodan Products satır döndüren CategoryID bir SQL deyimiyle veritabanını sorgular.

Sistemdeki N kategorileri göz önünde bulundurulduğunda, bu yaklaşım tüm kategorileri almak için veritabanına bir veritabanı sorgusu ve ardından her kategoriye özgü ürünleri almak için N çağrılarını netler. Ancak, yalnızca iki veritabanı çağrısında tüm gerekli verileri alabilir, tüm kategorileri almak için bir çağrı ve tüm ürünleri almak için başka bir çağrı. Tüm ürünlere sahip olduktan sonra, bu ürünleri filtreleyebiliriz, böylece yalnızca güncel CategoryID ürünle eşleşen ürünler bu kategorinin iç Repeater'sine bağlı olur.

Bu işlevselliği sağlamak için yalnızca ASP.NET sayfamızın arka kod arkası sınıfında yönteminde küçük bir değişiklik GetProductsInCategory(categoryID) yapmamız gerekir. Sınıf yönteminin ProductsBLL sonuçlarını körü körüne döndürmek yerine, önce tüm ürünlere erişebilir (henüz erişilmemişse) ve ardından geçirilen CategoryIDöğesine göre ürünlerin yalnızca filtrelenmiş görünümünü döndürebiliriz.GetProductsByCategoryID(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 allProductseklenmesine dikkat edin. Bu, tüm ürünlerle ilgili bilgileri tutar ve yöntem ilk kez GetProductsInCategory(categoryID) çağrıldığında doldurulur. Nesnenin allProducts oluşturulduğundan ve dolduruldığından emin olduktan sonra yöntemi DataTable sonuçlarını yalnızca belirtilen CategoryID satırlarla eşleşen satırların CategoryID erişilebilir olmasını sağlayacak şekilde filtreler. Bu yaklaşım, veritabanına N + 1'den ikiye kadar erişim sayısını azaltır.

Bu geliştirme, sayfanın işlenmiş işaretlemesinde herhangi bir değişiklik getirmez ve diğer yaklaşımdan daha az kayıt getirmez. Yalnızca veritabanına yapılan çağrı sayısını azaltır.

Not

Veritabanı erişimlerinin sayısının azaltılmasının performansı kesinlikle artıracağı sezgisel bir neden olabilir. Ancak bu durum söz konusu olmayabilir. Örneğin, olan CategoryIDNULLçok sayıda ürününüz varsa, yöntemine GetProducts yapılan çağrı hiçbir zaman görüntülenmeyen bir dizi ürün döndürür. Ayrıca, kategorilerin yalnızca bir alt kümesini gösteriyorsanız tüm ürünlerin döndürülmesi gereksiz olabilir. Bu, disk belleği uyguladıysanız bu durum söz konusu olabilir.

Her zaman olduğu gibi, iki tekniğin performansını analiz etmek söz konusu olduğunda, tek emin olunan ölçü uygulamanızın yaygın durum senaryoları için uyarlanmış kontrollü testler çalıştırmaktır.

Özet

Bu öğreticide, bir veri Web denetiminin başka bir veri içinde nasıl iç içe yerleştirildiğinden, özellikle bir dış Repeater'ın madde işaretli bir listede her kategoriye ait ürünleri listeleyen bir iç Repeater ile her kategori için bir öğe görüntülemesini incelemeyi gördük. İç içe bir kullanıcı arabirimi oluşturmanın temel zorluğu, doğru verilere erişmek ve iç veri Web denetimine bağlamaktır. Bu öğreticide incelediğimiz çeşitli teknikler vardır. İncelenen ilk yaklaşım, dış veri Web denetiminde, özelliği aracılığıyla DataSourceID iç veri Web denetimine ItemTemplate bağlı olan bir ObjectDataSource kullandı. İkinci teknik, ASP.NET sayfasının arka kod arkası sınıfındaki bir yöntem aracılığıyla verilere erişildi. Bu yöntem daha sonra veri bağlama söz dizimi aracılığıyla iç veri Web denetimi s DataSource özelliğine bağlanabilir.

Bu öğreticide incelenen iç içe kullanıcı arabirimi Bir Repeater içinde iç içe bir Repeater kullansa da, bu teknikler diğer veri Web denetimlerine genişletilebilir. Bir Repeater'ı bir GridView içinde veya GridView'ı DataList içinde iç içe yerleştirebilirsiniz.

Mutlu Programlama!

Yazar hakkında

Yedi ASP/ASP.NET kitabının yazarı ve 4GuysFromRolla.com kurucusu Scott Mitchell, 1998'den beri Microsoft Web teknolojileriyle çalışmaktadır. Scott bağımsız bir danışman, eğitmen ve yazar olarak çalışmaktadır. Son kitabı Sams Teach Yourself ASP.NET 24 Saat içinde 2.0. Adresine adresinden veya adresinden ulaşabileceğiniz http://ScottOnWriting.NETblogu aracılığıyla ulaşabilirsinizmitchell@4GuysFromRolla.com.

Özel Teşekkürler

Bu öğretici serisi birçok yararlı gözden geçiren tarafından gözden geçirildi. Bu öğreticinin baş gözden geçirenleri Zack Jones ve Liz Shulok'tur. Yaklaşan MSDN makalelerimi gözden geçirmek istiyor musunuz? Öyleyse, bana bir satır mitchell@4GuysFromRolla.combırakın.