WPF Mimarisi
Bu konu başlığında Windows Presentation Foundation (WPF) sınıf hiyerarşisine yönelik kılavuzlu bir tur sunulmaktadır. WPF'nin ana alt sistemlerinin çoğunu kapsar ve bunların nasıl etkileşime geçtiğini açıklar. Ayrıca WPF'nin mimarları tarafından yapılan bazı seçimlerin ayrıntıları da yer alır.
System.Object
Birincil WPF programlama modeli yönetilen kod aracılığıyla kullanıma sunulur. WPF'nin tasarım aşamasında, sistemin yönetilen bileşenleri ile yönetilmeyen bileşenler arasında çizginin nereye çekilmesi gerektiği konusunda bir dizi tartışma vardı. CLR, geliştirmeyi daha üretken ve sağlam hale getiren (bellek yönetimi, hata işleme, ortak tür sistemi vb.) bir dizi özellik sağlar, ancak bunların bir maliyeti vardır.
WPF'nin ana bileşenleri aşağıdaki şekilde gösterilmiştir. Diyagramın kırmızı bölümleri (PresentationFramework, PresentationCore ve milcore), WPF'nin ana kod bölümleridir. Bunlardan yalnızca biri yönetilmeyen bir bileşendir : milcore. Milcore, DirectX ile sıkı tümleştirmeyi etkinleştirmek için yönetilmeyen kodla yazılır. WPF'deki tüm görüntüler DirectX altyapısı aracılığıyla yapılır ve verimli donanım ve yazılım işlemeye olanak sağlar. WPF ayrıca bellek ve yürütme üzerinde de ince denetime ihtiyaç duyuyor. Milcore'daki bileşim altyapısı son derece performansa duyarlıdır ve performans elde etmek için CLR'nin birçok avantajından vazgeçmeyi gerektirir.
WPF'nin yönetilen ve yönetilmeyen bölümleri arasındaki iletişim, bu konunun ilerleyen bölümlerinde ele alınmıştır. Yönetilen programlama modelinin geri kalanı aşağıda açıklanmıştır.
System.Threading.DispatcherObject
WPF'deki nesnelerin çoğu, eşzamanlılık ve iş parçacığı ile ilgilenmek için temel yapıları sağlayan dosyasından DispatcherObjecttüretilir. WPF, dağıtıcı tarafından uygulanan bir mesajlaşma sistemini temel alır. Bu, tanıdık Win32 ileti pompasına çok benzer; aslında WPF dağıtıcısı, çapraz iş parçacığı çağrıları gerçekleştirmek için User32 iletilerini kullanır.
WPF'de eşzamanlılık tartışılırken anlaşılması gereken gerçekten iki temel kavram vardır: dağıtıcı ve iş parçacığı benzitesi.
WPF'nin tasarım aşamasında amaç, tek bir yürütme iş parçacığına, ancak iş parçacığı olmayan "affinitized" modeline geçmekti. bir bileşen, bir tür durumu depolamak için yürütülen iş parçacığının kimliğini kullandığında iş parçacığı benzitesi oluşur. Bunun en yaygın biçimi, durumu depolamak için iş parçacığı yerel depoyu (TLS) kullanmaktır. İş parçacığı benzitesi, her mantıksal yürütme iş parçacığının işletim sistemindeki yalnızca bir fiziksel iş parçacığına sahip olmasını gerektirir ve bu da bellek yoğunluklu hale gelebilir. Sonunda WPF'nin iş parçacığı modeli, iş parçacığı benzimliği ile tek iş parçacıklı yürütmenin mevcut User32 iş parçacığı modeliyle eşitlenmiş olarak tutuldu. Bunun birincil nedeni birlikte çalışabilirlikti: OLE 2.0, pano ve Internet Explorer gibi sistemlerin tümü için tek iş parçacığı benşimi (STA) yürütmesi gerekir.
STA iş parçacığına sahip nesneleriniz olduğu düşünüldüğünde, iş parçacıkları arasında iletişim kurmak ve doğru iş parçacığında olduğunuzu doğrulamak için bir yönteme ihtiyacınız vardır. Burada dağıtıcının rolü yatıyor. Dağıtıcı, birden çok öncelikli kuyruğa sahip temel bir ileti gönderme sistemidir. İletilere örnek olarak ham giriş bildirimleri (fare taşındı), çerçeve işlevleri (düzen) veya kullanıcı komutları (bu yöntemi yürüt) verilebilir. öğesinden DispatcherObjecttüreterek, STA davranışına sahip bir CLR nesnesi oluşturursunuz ve oluşturma sırasında dağıtıcıya bir işaretçi verilir.
System.Windows.DependencyObject
WPF oluştururken kullanılan birincil mimari felsefelerden biri, yöntemler veya olaylara göre özelliklere yönelik bir tercihti. Özellikler bildirim temellidir ve eylem yerine amacı daha kolay belirtmenizi sağlar. Bu, kullanıcı arabirimi içeriğini görüntülemek için model temelli veya veri temelli bir sistemi de destekler. Bu felsefe, bir uygulamanın davranışını daha iyi denetlemek için bağlanabileceğiniz daha fazla özellik oluşturmanın amaçlanan etkisine sahipti.
Özelliklerin kullandığı sistemin daha fazlasına sahip olmak için, CLR'nin sağladığından daha zengin bir özellik sistemi gerekiyordu. Bu zenginliğe basit bir örnek, değişiklik bildirimleridir. İki yönlü bağlamayı etkinleştirmek için, değişiklik bildirimini desteklemek için bağlamanın her iki tarafına da ihtiyacınız vardır. Davranışın özellik değerlerine bağlı olması için özellik değeri değiştiğinde size bildirilmesi gerekir. Microsoft .NET Framework, bir nesnenin değişiklik bildirimleri yayımlamasına izin veren INotifyPropertyChange arabirimine sahiptir, ancak isteğe bağlıdır.
WPF, türünden DependencyObject türetilmiş daha zengin bir özellik sistemi sağlar. Özellik sistemi, özellik ifadeleri arasındaki bağımlılıkları izlediği ve bağımlılıklar değiştiğinde özellik değerlerini otomatik olarak yeniden doğrulayan bir "bağımlılık" özellik sistemidir. Örneğin, devralan (gibi FontSize) bir özelliğiniz varsa, özellik değeri devralan bir öğenin üst öğesinde değişirse sistem otomatik olarak güncelleştirilir.
WPF özellik sisteminin temeli bir özellik ifadesi kavramıdır. WPF'nin bu ilk sürümünde özellik ifade sistemi kapatılır ve ifadelerin tümü çerçevenin bir parçası olarak sağlanır. İfadeler, özellik sisteminde veri bağlama, stil oluşturma veya devralma işleminin sabit kodlanmış olmamasının, çerçevenin daha sonraki katmanları tarafından sağlanmasının nedenidir.
Özellik sistemi ayrıca özellik değerlerinin seyrek depolanmasını sağlar. Nesneler onlarca (yüzlerce değilse) özelliğe sahip olabileceğinden ve değerlerin çoğu varsayılan durumunda olduğundan (devralınan, stiller tarafından ayarlanan vb.), nesnenin her örneğinde tanımlanan her özelliğin tam ağırlığı olması gerekmez.
Özellik sisteminin son yeni özelliği, ekli özelliklerin gösterimidir. WPF öğeleri, oluşturma ve bileşen yeniden kullanımı ilkesine göre oluşturulur. Genellikle bazı içeren öğenin (düzen öğesi gibi Grid ) davranışını denetlemek için alt öğeler üzerinde ek verilere ihtiyaç duyduğu durumdur (Satır/Sütun bilgileri gibi). Bu özelliklerin tümünü her öğeyle ilişkilendirmek yerine, herhangi bir nesnenin diğer herhangi bir nesne için özellik tanımları sağlamasına izin verilir. Bu, JavaScript'in "expando" özelliklerine benzer.
System.Windows.Media.Visual
Bir sistem tanımlandığında, bir sonraki adım pikselleri ekrana çekme işlemidir. Visual sınıfı, her biri isteğe bağlı olarak bu yönergelerin nasıl işlenmesi (kırpma, dönüştürme vb.) hakkında çizim yönergelerini ve meta verileri içeren bir görsel nesne ağacı oluşturmayı sağlar. Visual son derece hafif ve esnek olacak şekilde tasarlanmıştır, bu nedenle özelliklerin çoğu genel API'ye maruz kalmaz ve korumalı geri çağırma işlevlerine yoğun bir şekilde güvenir.
Visual WPF oluşturma sisteminin giriş noktasıdır. Visual , yönetilen API ve yönetilmeyen milcore olan bu iki alt sistem arasındaki bağlantı noktasıdır.
WPF, milcore tarafından yönetilen yönetilmeyen veri yapılarını geçirerek verileri görüntüler. Oluşturma düğümleri olarak adlandırılan bu yapılar, her düğümde işleme yönergeleri içeren hiyerarşik bir görüntüleme ağacını temsil eder. Aşağıdaki şeklin sağ tarafında gösterilen bu ağaca yalnızca bir mesajlaşma protokolü aracılığıyla erişilebilir.
WPF'yi programlama sırasında, bu mesajlaşma protokolü aracılığıyla oluşturma ağacıyla dahili olarak iletişim kuran öğeler ve türetilmiş türler oluşturursunuz Visual . WPF'deki her Visual biri bir, hiçbiri veya birkaç oluşturma düğümü oluşturabilir.
Burada dikkat edilmesi gereken çok önemli bir mimari ayrıntı vardır; görseller ve çizim yönergelerinin tamamı önbelleğe alınır. Grafik terimleriyle WPF, korunan bir işleme sistemi kullanır. Bu, oluşturma sistemi kullanıcı koduna yapılan geri çağrıları engellemeden sistemin yüksek yenileme hızlarında yeniden boyanmasına olanak tanır. Bu, yanıt vermeyen bir uygulamanın görünümünü önlemeye yardımcı olur.
Diyagramda gerçekten fark edilemeyen bir diğer önemli ayrıntı da sistemin oluşturma işlemini nasıl gerçekleştirdiğini gösterir.
User32 ve GDI'da sistem, anında mod kırpma sisteminde çalışır. Bir bileşenin işlenmesi gerektiğinde sistem, bileşenin piksellere dokunmasına izin verilmeyen bir kırpma sınırları oluşturur ve ardından bileşenden bu kutudaki pikselleri boyaması istenir. Bu sistem, bellek kısıtlanmış sistemlerde çok iyi çalışır çünkü bir şey değiştiğinde yalnızca etkilenen bileşene dokunmanız gerekir; hiçbir iki bileşen tek bir pikselin rengine katkıda bulunmaz.
WPF bir "boyacı algoritması" boyama modeli kullanır. Başka bir deyişle, her bileşeni kırpmak yerine her bileşenin arka tarafından ekranın önüne işlenmesi istenir. Bu, her bileşenin önceki bileşenin ekranını boyamasına olanak tanır. Bu modelin avantajı karmaşık, kısmen saydam şekillere sahip olmanızdır. Günümüzün modern grafik donanımıyla bu model nispeten hızlıdır (User32/ GDI oluşturulduğunda bu durum geçerli değildi).
Daha önce belirtildiği gibi WPF'nin temel felsefesi daha bildirim temelli, "özellik merkezli" bir programlama modeline geçmektir. Görsel sistemde bu, birkaç ilginç yerde gösterilir.
İlk olarak, korumalı mod grafik sistemi hakkında düşünürseniz, bu durum kesinlik temelli bir DrawLine/DrawLine türü modelden veri odaklı modele ( yeni Çizgi()/yeni Çizgi()) geçiş yapmaktır. Bu veri temelli işlemeye taşıma, çizim yönergelerindeki karmaşık işlemlerin özellikler kullanılarak ifade edilmesini sağlar. öğesinden Drawing türetilen türler etkili bir şekilde işleme için nesne modelidir.
İkincisi, animasyon sistemini değerlendirirseniz neredeyse tamamen bildirim temelli olduğunu görürsünüz. Bir geliştiricinin sonraki konumu veya sonraki rengi hesaplamasını gerektirmek yerine, animasyonları bir animasyon nesnesinde bir özellik kümesi olarak ifade edebilirsiniz. Bu animasyonlar daha sonra geliştiricinin veya tasarımcının amacını ifade edebilir (bu düğmeyi 5 saniye içinde buradan oraya taşıyabilir) ve sistem bunu gerçekleştirmenin en verimli yolunu belirleyebilir.
System.Windows.UIElement
UIElement Düzen, Giriş ve Olaylar dahil olmak üzere temel alt sistemleri tanımlar.
Düzen, WPF'de temel bir kavramdır. Birçok sistemde sabit bir düzen modeli kümesi vardır (HTML düzen için üç modeli destekler; akış, mutlak ve tablolar) veya düzen için model yoktur (User32 yalnızca mutlak konumlandırmayı gerçekten destekler). WPF, geliştiricilerin ve tasarımcıların kesinlik temelli mantık yerine özellik değerleriyle yönlendirilebilen esnek, genişletilebilir bir düzen modeli istediği varsayımıyla başladı. UIElement Bu düzeyde, düzen için temel sözleşme tanıtılır: ile ve Arrange ile iki fazlı bir model Measure geçer.
Measure bir bileşenin ne kadar boyut almak istediğinizi belirlemesine izin verir. Bu, bir üst öğenin en uygun konumunu ve boyutunu belirlemek için bir alt öğeden birkaç kez ölçmesini isteyeceği birçok durumdan Arrange ayrı bir aşamadır. Üst öğelerin alt öğelerin ölçülmesini istemesi WPF'nin başka bir temel felsefesini gösterir– içeriğe boyut. WPF'deki tüm denetimler, içeriklerinin doğal boyutuna göre boyutlandırma özelliğini destekler. Bu, yerelleştirmeyi çok daha kolay hale getirir ve öğeler yeniden boyutlandırdıkça öğelerin dinamik düzenini sağlar. Aşama, Arrange bir ebeveynin her alt öğeyi konumlandırmasına ve son boyutunu belirlemesine olanak tanır.
Çoğunlukla WPF'nin Visual çıkış tarafı ve ilgili nesneler hakkında konuşarak çok fazla zaman harcanır. Ancak giriş tarafında da çok büyük miktarda yenilik vardır. WPF için giriş modelindeki büyük olasılıkla en temel değişiklik, giriş olaylarının sistem üzerinden yönlendirildiği consis çadır modu l değeridir.
Giriş, çekirdek modu cihaz sürücüsünde bir sinyal olarak kaynaklanır ve Windows çekirdeği ve User32'yi içeren karmaşık bir işlem aracılığıyla doğru işleme ve iş parçacığına yönlendirilir. Girişe karşılık gelen User32 iletisi WPF'ye yönlendirildikten sonra WPF ham giriş iletisine dönüştürülür ve dağıtıcıya gönderilir. WPF, ham giriş olaylarının birden çok gerçek olaya dönüştürülmesini sağlar ve "MouseEnter" gibi özelliklerin sistemin düşük bir düzeyinde ve garantili teslimle uygulanmasını sağlar.
Her giriş olayı en az iki olaya dönüştürülür: bir "önizleme" olayı ve gerçek olay. WPF'deki tüm olaylar, öğe ağacı üzerinden yönlendirmeye ilişkin bir nota sahiptir. Olaylar, ağaçtan köke doğru bir hedeften geçerse "kabarcık" olarak adlandırılır ve kökten başlayıp bir hedefe doğru aşağı doğru ilerlerse "tünel" olarak adlandırılır. Giriş önizleme olayları tüneli, ağaçtaki herhangi bir öğeyi etkinleştirerek olay üzerinde filtreleme veya eylem gerçekleştirme fırsatı sunar. Normal (önizleme olmayan) olaylar daha sonra hedeften köke kadar kabarır.
Tünel ve kabarcık aşaması arasındaki bu bölme, klavye hızlandırıcıları gibi özelliklerin bileşik dünyada tutarlı bir şekilde çalışmasını sağlar. User32'de, desteklemek istediğiniz tüm hızlandırıcıları içeren tek bir genel tabloya sahip olarak (Ctrl+N ile "Yeni" eşlemesi) klavye hızlandırıcıları uygularsınız. Uygulamanızın dağıtıcısında TranslateAccelerator'ı çağırarak User32'deki giriş iletilerinin kokusunu alır ve kayıtlı bir hızlandırıcıyla eşleşip eşleşmediğini belirlersiniz. WPF'de sistem tamamen "birleştirilebilir" olduğundan bu işe yaramaz; herhangi bir öğe herhangi bir klavye hızlandırıcısını işleyebilir ve kullanabilir. Giriş için bu iki aşama modeline sahip olmak, bileşenlerin kendi "TranslateAccelerator" uygulamalarını sağlar.
Bunu bir adım daha ileriye UIElement götürmek için CommandBindings'i de tanıtır. WPF komut sistemi, geliştiricilerin bir komut bitiş noktası (uygulayan ICommandbir şey) açısından işlevsellik tanımlamasına olanak tanır. Komut bağlamaları, bir öğenin giriş hareketi (Ctrl+N) ile komut (Yeni) arasında eşleme tanımlamasını sağlar. Hem giriş hareketleri hem de komut tanımları genişletilebilir ve kullanım zamanında birlikte bağlanabilir. Bu, örneğin son kullanıcının uygulama içinde kullanmak istediği anahtar bağlamalarını özelleştirmesine izin vermenizi önemsiz hale getirir.
Konu başlığındaki bu noktaya kadar, WPF'nin "çekirdek" özellikleri – PresentationCore derlemesinde uygulanan özellikler odak noktası olmuştur. WPF oluştururken, temel parçalar (Ölçü ve Düzenleme ile düzen sözleşmesi gibi) ve çerçeve parçaları (gibi belirli bir düzenin uygulanması gibiGrid) arasında temiz bir ayrım istenen sonuçtu. Amaç, yığında dış geliştiricilerin gerekirse kendi çerçevelerini oluşturmasına olanak sağlayacak bir genişletilebilirlik noktası sağlamaktı.
System.Windows.FrameworkElement
FrameworkElement iki farklı şekilde bakılabilir. WPF'nin alt katmanlarında sunulan alt sistemlerde bir dizi ilke ve özelleştirme sunar. Ayrıca bir dizi yeni alt sistemi de tanıtır.
tarafından FrameworkElement sunulan birincil ilke, uygulama düzeniyle ilgilidir. FrameworkElement tarafından UIElement sunulan temel düzen sözleşmesini temel alır ve düzen yazarlarının tutarlı bir özellik temelli düzen semantiği kümesine sahip olmasını kolaylaştıran bir düzen "yuva" fikri ekler. , , ve Margin (birkaçını adlandırmak için) gibi HorizontalAlignmentözellikler, düzen kapsayıcılarının içindeki tutarlı davranıştan FrameworkElement türetilen tüm bileşenleri MinWidthverir. VerticalAlignment
FrameworkElement ayrıca WPF'nin çekirdek katmanlarında bulunan birçok özelliğe daha kolay API'nin maruz kalmasını sağlar. Örneğin, FrameworkElement yöntemi aracılığıyla BeginStoryboard animasyona doğrudan erişim sağlar. A Storyboard , bir dizi özellik için birden çok animasyon betiği oluşturmanın bir yolunu sağlar.
En önemli iki şey FrameworkElement , veri bağlama ve stillerdir.
WPF'deki veri bağlama alt sistemi, uygulama kullanıcı arabirimi (UI) oluşturmak için Windows Forms veya ASP.NET kullanan herkes için nispeten tanıdık olmalıdır. Bu sistemlerin her birinde, belirli bir öğedeki bir veya daha fazla özelliğin bir veri parçasına bağlanmasını istediğinizi ifade etmenin basit bir yolu vardır. WPF özellik bağlama, dönüştürme ve liste bağlama için tam desteğe sahiptir.
WPF'de veri bağlamanın en ilginç özelliklerinden biri, veri şablonlarının tanıtılmasıdır. Veri şablonları, bir veri parçasının nasıl görselleştirilmesi gerektiğini bildirimli olarak belirtmenize olanak sağlar. Verilere bağlanabilecek özel bir kullanıcı arabirimi oluşturmak yerine, sorunu geçici hale getirebilir ve verilerin oluşturulacak görüntüyü belirlemesine izin vekleyebilirsiniz.
Stil oluşturma, gerçekten basit bir veri bağlama biçimidir. Stil oluşturmayı kullanarak paylaşılan bir tanımdan bir veya daha fazla öğe örneğine bir özellik kümesi bağlayabilirsiniz. Stiller bir öğeye açık başvuruyla (özelliği ayarlayarak Style ) veya örtük olarak bir stili öğenin CLR türüyle ilişkilendirerek uygulanır.
System.Windows.Controls.Control
Denetimin en önemli özelliği şablon oluşturmadır. WPF'nin oluşturma sistemini korumalı mod işleme sistemi olarak düşünüyorsanız, şablon oluşturma, denetimin işlemesini parametreli, bildirim temelli bir şekilde tanımlamasına olanak tanır. A ControlTemplate , denetim tarafından sunulan özelliklere bağlamalar içeren bir alt öğe kümesi oluşturmak için bir betikten başka bir şey değildir.
Control, ForegroundBackgroundşablon yazarlarının bir denetimin görünümünü özelleştirmek için kullanabilecekleri, birkaçını adlandırmak için , , Padding, adlı bir dizi hisse senedi özelliği sağlar. Denetimin uygulanması bir veri modeli ve etkileşim modeli sağlar. Etkileşim modeli bir komut kümesini (pencere için kapat gibi) tanımlar ve giriş hareketlerine bağlar (pencerenin üst köşesindeki kırmızı X işaretine tıklama gibi). Veri modeli, etkileşim modelini özelleştirmek veya görüntüyü özelleştirmek için bir özellik kümesi sağlar (şablon tarafından belirlenir).
Bu, veri modeli (özellikler), etkileşim modeli (komutlar ve olaylar) ve görüntüleme modeli (şablonlar) arasında bölünerek denetimin görünümünün ve davranışının tam olarak özelleştirilmesini sağlar.
Denetimlerin veri modelinin yaygın bir yönü con çadır modu l'dir. gibi Buttonbir denetime bakarsanız, türünde Object"content" adlı bir özelliği olduğunu görürsünüz. Windows Forms ve ASP.NET'da bu özellik genellikle bir dize olur; ancak bu, bir düğmeye yerleştirebileceğiniz içerik türünü sınırlar. Bir düğmenin içeriği basit bir dize, karmaşık bir veri nesnesi veya öğe ağacının tamamı olabilir. Veri nesnesi söz konusu olduğunda, bir görüntü oluşturmak için veri şablonu kullanılır.
Özet
WPF, dinamik, veri odaklı sunu sistemleri oluşturmanıza olanak sağlayacak şekilde tasarlanmıştır. Sistemin her bölümü, davranışı yönlendiren özellik kümeleri aracılığıyla nesneler oluşturmak üzere tasarlanmıştır. Veri bağlama, sistemin temel bir parçasıdır ve her katmanda tümleştirilir.
Geleneksel uygulamalar bir görüntü oluşturur ve ardından bazı verilere bağlanır. WPF'de, denetimin her yönüyle ilgili her şey bir tür veri bağlaması tarafından oluşturulur. Düğmenin içinde bulunan metin, düğmenin içinde oluşturulmuş bir denetim oluşturularak ve görünümünü düğmenin içerik özelliğine bağlayarak görüntülenir.
WPF tabanlı uygulamalar geliştirmeye başladığınızda çok tanıdık geliyor olmalıdır. Windows Forms veya ASP.NET ile aynı şekilde özellikleri ayarlayabilir, nesneleri ve veri bağlamayı kullanabilirsiniz. WPF mimarisine yönelik daha ayrıntılı bir araştırmayla, verileri temel olarak uygulamanın temel sürücüsü olarak değerlendiren çok daha zengin uygulamalar oluşturma olasılığının mevcut olduğunu göreceksiniz.
Ayrıca bkz.
.NET Desktop feedback