János's profileJanka JánosPhotosBlogListsMore ![]() | Help |
Janka JánosMicrosoft Fejlesztői Blog Köszönjük a látogatást!
Manówrote:
Szia János!
Itt jártam. Érdekes ez a tárhely.
Andi.
Apr. 29
Tibor Szűcswrote:
Szia János!
Az áprilisi blogbejegyzésed nagy segítséget nyújtott a munkámban. Köszi...
Dec. 11
|
July 03 DE – Prog. infoOh, látom még mindig jók az arányok. A mostani ki sincs téve. Biztos túl sokan végeztek, nem fért ki a lapra. Programtervező informatikust még nem is láttam kiírva, ahogy elnézem, pedig az BSc.-s szak, így 3 éves az alapképzés. Már lennie kellene valakinek azóta régen. Azt hittem valamelyik volt csoport-társam már végzett azóta. A főiskolai szakot (programozó matematikus) is már mikor megszűntették, de még látom, hogy vannak befutók. Biztos túl könnyű volt a kalkulus. ;) Ahogy látom a tematika se változott nagyon. Első 1/1.5 év tömény matek, majd csak utána jön a “lényeg”. Most nézem, hogy az informatikus könyvtáros szak meg tiszta elvont tárgyakkal van tele. Király, főleg hogy a kutyát nem érdekli most, hogy milyen diplomád van, csak szakirányú végzettség legyen. Ja, meg még ráadásul sokkal kevesebb kreditet is kell megszerezni hozzá kevesebb óraszámmal. Na nem is ez itt a lényeg, hanem sokkal inkább az, hogy ki mit gondol arról, mennyire van köze az iskolai végzettségnek a üzleti életben való helytálláshoz, sikerességhez? Azért is teszem fel ezt a kérdést, mert engem is sokszor bonbáznak/bonbáztak ezügyben. Írtam ide egy regényt előzőleg, de kiszedtem, nehogy befolyásoljam bárki válaszát is. :) June 28 SQL Server adatbázisok szinkronizálásaErre a témára kénytelen vagyok egy picivel több szót fecsérelni, mert ez az, ami az életben is talán a legtöbbször előfordul. Több megoldás is létezik egyébként a problémára. Egyik ezek közül a Microsoft SQL Server Integration Services használata. Ez utóbbival egyetlen probléma, hogy SQL Server Express felhasználók nem tudják használni. Másik megoldás a Sync Framework használata, én most ezzel fogok folglalkozni, mely nem csak kiadás-független, hanem SQL Server független is. Még mielőtt tovább mennénk, vegyünk egy pillantást a provider modellre, ami lényegesen változott az első CTP óta: Mint látható a képen, az újítások javarésze az adatbázisok szinkronizálását célozta meg. Született egy új, a relációs adatbázisok szinkronizálására alkalmas provider RelationalSyncProvider néven. Ennek leszármazottja egy DbSyncProvider, mely egy általános célú adatbázis szinkronizáló provider, illetve két specializált provider, melyek SQL Server / SQL CE adatbázisokhoz készültek (SqlSyncProvider, SqlCeSyncProvider). Mi most az utóbbi kettővel fogunk foglalkozni, de ez nem jelenti azt, hogy maga a feladat csupán ezekkel oldható meg. Ha saját változás-követési infrastruktúrát szeretnénk kialakítani, illetve magunk szeretnénk kezelni az alacsonyszintű metaadattárolási műveleteket, akkor még mindig lehetőség adódik használni ezek őseit. Néhány előnyét azért mégis felsorolnám a készhez kapott SqlSync providereknek:
Alapvető Sql Sync fogalmak Szinkronizálása a csomópontoknak egy topológiában két fázisra bontható: a szinkronizációs csomópontok beállítása, illetve futtatása a szinkronizációnak egypár csomópont között. Az SqlSync providerek esetében a csomópontok beállítása két feladatból áll: 1. Definiálni, hogy mit szeretnénk szinkronizálni private DbSyncTableDescription SetPrimaryKeys(DbSyncTableDescription tableSchema, params string[] keys) { Contract.Requires(tableSchema != null); Contract.Requires(keys != null); Contract.Requires(Contract.ForAll(keys, key => key != null)); for (var i = tableSchema.Columns.Count - 1; i >= 0; i--) { var column = tableSchema.Columns[i]; if (column.IsPrimaryKey && column.AutoIncrementStepSpecified) { tableSchema.Columns.Remove(column); } else { column.IsPrimaryKey = keys.Contains(column.UnquotedName); } } return tableSchema; } 2. Az adatbázisok ellátása változás-követési információkkal Szinkronizációs területek (scopes) Fontos megérteni, hogy egy scope kombinációja tábláknak és szűréseknek. Definiálhatunk olyan scope-ot is, ami csak a debreceni cégeket szinkronizálja, de mellé még egy olyat is, ami csak a pesti cégeket. Megjegyzendő, hogy a SyncFx nem kezeli azokat a törlési eseteket, amikor például egy debreceni cégből pesti lesz. Ilyenkor az egyik scope-ból átkerül a másikba az adat a szűrési kritériumok miatt, de a régi scope-ból nekünk kell azt törölni. Az alkalmazás feladata kezelni ezt a szituációt. Amennyiben nem szűrögetünk, hanem ökör módjára mindent szinkronizálunk (mint én is :)), ilyen gond nincs. A scope-ok lehetnek eltérőek, vagy átfedhetik egymást. Két scope átfedi egymást, ha egymás között osztanak meg közös adatokat. Van egy pár lehetőség scope-ok definiálására, de a következő elvet mindenesetben követni kell: bármilyen adat ami szinkronizált két adatbázis között a szinkronizációs topológiában csak egy scope-hoz tartozhat. Például az A és B adatbázis szinkronizálhat a Scope 1-el, az A és C adatbázis pedig a Scope 2-el egymás között. Az A és B nem tud szinkronizálni a Scope 2-el, mert az adott tábla sorok (pl. termékek) mindkét scope-hoz hozzátartoznak. Hogyan is működik ez a gyakorlatban? Először is, leírjuk a scope-ot és a táblákat. Én ezen általánosítottam egy picit, mint ahogy az SDK-ban van: /// <summary> Fontos látni, hogy a konfigurálásnak ez csak az egyik módja. Jelen esetben a meghatározott scope-ot és sémát alkalmazzuk először a szerverre, azt követően pedig a kliensre, de lehetőség van már magából a szerverből kinyerni a szinkronizációs sémát (ha már ott létezik) és azt alkalmazni a kliens adatbázisra. Ez utóbbi módszer különösen hasznos, ha biztosítani szeretnénk, hogy konzisztens maradjon a szerver szinkronizációs séma a kliensével. Használatára egy példa (a tábla sorrend számít): ApplyConfig(ScopeFromTableSchemas
(
GetTableSchema("Country"),
GetTableSchema("StateProvince"),
GetTableSchema("Settlement")
Ha ezzel idáig megvagyunk és megnézzük az adatbázist, akkor láthatjuk, hogy létrejöttek a change-tracking meta-adat táblák/triggerek/tárolt eljárások a szerveren és a kliensen egyaránt. Amennyiben valami gubanc van a létrehozás közben, megtehetjük azt is, hogy az infrastruktúrát létrehozó SQL scriptet még az alkalmazási folyamat előtt kimentjük például egy fájlba és mi magunk kézzel kezdjük el javítgatgni, majd futtatni azt az SQL Management Studio segítségével: Ezt még a config.Apply() előtt meg kell tenni, ha esetleg valami probléma adódna a script futtatásakor. Utolsó lépésben pedig semmi más dolgunk nincs, mint egy SyncOrchestrator-t felhasználva szinkronizálni a két csomópont között: public void Synchronize() { Init(); var clientProvider = new SqlSyncProvider(ScopeName, ClientConnection); var serverProvider = new SqlSyncProvider(ScopeName, ServerConnection); Orchestrator.Direction = SyncDirectionOrder.UploadAndDownload; Orchestrator.LocalProvider = clientProvider; Orchestrator.RemoteProvider = serverProvider; clientProvider.SyncProgress += ...; serverProvider.SyncProgress += ...; clientProvider.ApplyChangeFailed += ...; DisplayStat(Orchestrator.Synchronize()); } A kliens és a szerver szinkronizáció is szépen végigkövethető a SyncProgress események segítségével, de ezen felül kapunk egy végső összegzést is, amivel a Synchronize() szinkron metódus-hívás tér vissza. Az ApplyChangeFailed eseményre feliratkozva kezelhetjük a szinkronizálás közben bekövetkező konfliktusokat is a következő Action értékekből választva: private void clientProvider_ApplyChangeFailed(object sender, Mindebből egész jól látszik, hogy mennyire egyszerű szinkronizálni adatbázisok között. Ha van érdeklődés a téma iránt, akkor folytatom ezt a cikksorozatot a későbbiekben is, mert ez még hiányos egy picit, de ízelítőnek egyenlőre ennyi is elég. June 16 Balatonlelle (július 3.-4.-5.)Szeretném tudatni mindenkivel (hátha arra kószál valaki a blogomról), hogy a lellei juliális ezeken a napokon lesz és én is ott leszek. A főzőversenyen halászlét fogunk csinálni, mint minden évben, úgyhogy ha gondoljátok, ugorjatok le egy hétvégére és egy díjnyertes ebédre. Mellesleg ilyenkor mindig jó a felhozatal is. :) June 11 WPF 4.0 Data Binding PipelineA WPF 4.0 adatkötési pipeline-ba is történt némi változás, ami képes a tulajdonságok újraolvasására a kötési forrásból miután a control beállítja a tulajdonság értékét. Például:
Tehát mondhatjuk, hogy van egy új feedback mehanizmus, amit a WPF adatkötési motorja képes kezelni mostantól kezdve. XAML 2009 (.NET FX 4 Beta 1)Engedelmetekkel larántám a leplet néhány XAML 2009 újdonságról, mert kemény fejlesztéseken megy keresztül a WPF 4.0 is. Arról rengeteg hír van már most, hogy a VS Cider WPF designer designtime támogatása mennyit javult a VS2010-re - ténylegesen stabilabb és “egészségesebb” designer mint az előző verzió volt - de arról kevesen ejtenek szót, hogy a XAML nyelv merre fejlődik tovább. Megjegyzendő, hogy az alábbi XAML 2009 featurök még csak nyomokban működnek a VS 2010 Beta 1-ben. Például át kell állítani az adott XAML markup fájl Build Action tulajdonságát Page-ről Resource-ra, mely elkerüli, hogy a XAML markup leforduljon BAML/IL-re. Ez szükséges a Beta 1-ben, mivel az új nyelvi szintaxis még nem mindenhol támogatott. Illetve szükséges felvenni a System.Xaml assembly-t is a referenciák közé. Én ezeket az új featuröket úgy teszteltem, hogy készítettem egy ResourceDictionary-t, abba raktam DataTemplate-eket, majd az ablakba egy ContentPresenter segítségével megjelenítettem a tartalmat. Még mielőtt nyelvi dolgokról írnék, némi összefoglalóval szolgálnék már így az elején. Először is a XAML kezeléssel kapcsolatos létező összes kód folyamatosan kerül ki a System.Xaml.dll assembly-be a WindowsBase.dll-ből. Tehát maga a XAML nyelv teljesen WPF független lesz. Létezik egy új következetes XAML stack, ami megosztott mind WPF/WCF/WF között egyaránt. További jó hír, hogy egyetlen parser lesz x db helyett (sablonokhoz, stílusokhoz, stb.), ami garantálja a konzisztens viselkedést mindenhol. Ezenfelül a WPF team készít egy API-t BAML olvasáshoz, mely többek közt lehetőséget ad analizálni a XAML/BAML-t ugyanazzal az API-val… De ami igazán érdekel bennünket, hogy milyen nyelvi újdonságok várnak ránk: 1. Name References <DataTemplate x:Key="CT"> <StackPanel Orientation="Horizontal" VerticalAlignment="Top"> <TextBox Name="myTextBox" Width="200"/> <Label Target="{x:Reference myTextBox}" Content="Text"/> </StackPanel> Így már nem működik: <DataTemplate x:Key="CT"> <StackPanel Orientation="Horizontal" VerticalAlignment="Top"> <Label Target="{x:Reference myTextBox}" Content="Text"/> <TextBox Name="myTextBox" Width="200"/> </StackPanel> </DataTemplate> Valójában mindössze egy NameReferenceConverter nevű típuskonverter van a háttérben. Azt, hogy valójában mi egy típuskonverter, már korábban leírtam: itt. Illetve mégegy apróság, ellenben a Binding-al, ez nem támogatja az adatkontextus kötéseket {x:Reference} != {Binding}. 2. Generikus típusok támogatása XAML-ben <DataTemplate x:Key="Template"> <StackPanel Orientation="Horizontal" VerticalAlignment="Top"> <StackPanel.DataContext> <om:ObservableCollection x:TypeArguments="x:String"> <x:String>A</x:String> <x:String>B</x:String> <x:String>C</x:String> </om:ObservableCollection> </StackPanel.DataContext> <ListBox ItemsSource="{Binding}"/> </StackPanel> </DataTemplate> Generikus típus-paraméterek az új x:TypeArguments segítségével adhatók meg. Ez a példa egyben azt is demonstrálja, hogy mostantól az alap típusok az {xmlns:x:..} XAML névtéren belül úgyszint elérhetők, mint pl. a string típus is: <x:String/>. Nincs szükség 76 névteret felvenni. Több típus-argumentumot egymással vesszővel elválasztva adunk meg: <gcc:Dictionary x:TypeArguments="x:String, x:Double"/> Mi van akkor, ha egy generikus típus-paraméter is egy generikus típus? Semmi, ugyanis lehetőség van generikus típusok beágyazására is a következő szintaxissal: <gcc:Dictionary x:TypeArguments="x:String, gcc:List(x:Double)"/> 3. Egyszerűsített elérése az alap típusoknak Néhány példa:
4. Paraméter nélküli (nem default) konstruktorok és factory metódusok támogatása x:Arguments 5. Események XAML által XAML: Events in compiled and uncompiled scenarios Egyenlőre még nem nagyon merülök bele a további részletekbe, mert még a VS 2010 Beta 1 is nagyon gyengén muzsikál ezekkel a dolgokkal. Az viszont a napnál is világosabb, hogy a legnagyobb cél a közös XAML stack megalkotása, így pl. a WCF is ezt fogja használni. Ezzel megy el a legtöbb idő a csapaton belül (a nyilatkozatok alapján), mivel jóval bonyolultabb ezt kivitelezni, mint elsőre gondolták. June 10 SQL szerverből SQL szerverbeAz SqlSyncProvider használatával kapcsolatban készítettem egy nagyon alap kis demonstrációs bemutatót. Nem csalás, nem ámítás, ténylegesen ennyi kód megvalósítani az SQL Server adatbázisok közötti szinkronizációt: using System; using System.Data.SqlClient; using Microsoft.Synchronization; using Microsoft.Synchronization.Data; using Microsoft.Synchronization.Data.SqlServer; namespace VVMF.Samples.Sync { class Program { static void Main(string[] args) { // Helyi és távoli kapcsolatok létrehozása (SqlConnection). var localConnection = new SqlConnection( @"Data Source=local;Initial Catalog=DB1;Integrated Security=True"); var remoteConnection = new SqlConnection( @"Data Source=local;Initial Catalog=DB2;Integrated Security=True"); // Létrehoz egy szinkronizációs scope-ot, // amin belül minden látszik a SyncFx számára. var scopeDesc = new DbSyncScopeDescription("Filtered_Organization"); // Hozzáadjuk a scope-hoz az Organization táblát. // A GetDescriptionForTable() metódus kinyeri a tábla sémát. scopeDesc.Tables.Add( SqlSyncDescriptionBuilder.GetDescriptionForTable( "Organization", remoteConnection)); // Konfiguráljuk a szinkronizációs scope-ot. // Nem kell létrehozni a táblákat, mert már léteznek. var remoteConfig = new SqlSyncScopeProvisioning(scopeDesc); remoteConfig.SetCreateTableDefault(DbSyncCreationOption.Skip); // Jelen esetben csak az W betűvel keződőek lesznek szinkronizálva. remoteConfig["Organization"].AddFilterColumn("Name"); remoteConfig["Organization"].FilterClause = "[side].[Name] LIKE 'W%'"; // Konfiguráljuk a scope és változás-követési infrastruktúrát, // feltéve, hogy még nem létezik. Ez fogja létrehozni a táblanév_tracking // táblákat, illetve triggereket, SP-ket, stb. if (!remoteConfig.ScopeExists("Filtered_Organization", remoteConnection)) remoteConfig.Apply(remoteConnection); // A távoli adatbázison már elkészítettük a change tracking infrastruktúrát. // Itt csak kinyerjük a jelenlegi állapotot a szerverről és alkalmazzuk // a kliens adatbázisra is. var localSqlDesc = SqlSyncDescriptionBuilder .GetDescriptionForScope("Filtered_Organization", remoteConnection); var localConfig = new SqlSyncScopeProvisioning(localSqlDesc); if (!localConfig.ScopeExists("Filtered_Organization", localConnection)) localConfig.Apply(localConnection); // Helyi és távoli szinkronizációs providerek létrehozása (SqlSyncProvider). var orchestrator = new SyncOrchestrator(); orchestrator.LocalProvider = new SqlSyncProvider("Filtered_Organization", localConnection); orchestrator.RemoteProvider = new SqlSyncProvider("Filtered_Organization", remoteConnection); // Egyéni adat-transzformációs konverterek hozzáadása. // Jelen esetben szükségtelen, mert mindkét oldalon ugyanolyan // szerkezetben van ábrázolva a cég. // orchestrator.LocalDataConverter = ... // orchestrator.RemoteDataConverter = ... // Néhány eseménykezelő, hogy tudjuk hol tart a folyamat. orchestrator.StateChanged += (sender, e) => Console.WriteLine( A SyncFx minden mást megcsinál helyettünk. Íme az eredmény: Kb. 3 sorral több elintézni azt, hogy ez egy harmadik, teszem fel SQL Server Compact adatbázisba is leszinkronizálódjon. Természetesen amit fentebb mutattam csak egy alap példa, jóval testreszabhatóbb ennél a dolog. Például még a szinkronizáció során fenntartott cache memória mérete is szabályozható. Microsoft Sync Framework 2.0 CTP2A Sync csapat kiadta a következő CTP-t. Végre van szinkronizáció provider direkt SQL Server adatbázisokhoz is! Az újdonságokról röviden: SqlSyncProvider / SqlCeSyncProvider Custom filters Az egyéni szűrők lehetőséget adnak egy szűrt replikának hogy tároljon tételadatokat csak azon tételekhez, amelyek a szűrésben szerepelnek, mint pl. egy média tároló replika, mely csak tárolja azokat a dalokat, melyek az értékelés során legalább 3 csillagot kaptak. Amint megváltozik egy dal értékelése, egy tétel bekerülhet/kikerülhet a szűrésből. Egy szűrés-követő replika egy másik replika a közösségben, amely tudja azonosítani, hogy mely tételek szerepelnek a szűrésben és melyek voltak betéve/kivéve mostanában. Egy szűrés-követő replika tárolhat tétel adatokat azon tételekhez is, melyek nem szerepelnek a szűrésben. A Sync Framework támogatja a hatékony szinkronizációt a szűrt replikák és a szűrés-követő replikák között és gondoskodik a meta-adatok kezeléséről. Improved conflict handling A CTP2 hozzáad jónéhány új funkciót a SyncFx-hez, ami egyszerűsíti a szinkronizáció során előfordulható konfliktusok kezelését. További részletek erről itt. Data conversion between providers Na ez már egy érdekesebb dolog, főként, hogy nekem is pont ez kell. Néhány esetben a szinkronizációs providerek szinkronizálnak ugyanolyan típusú adatokat (jelen esetben nálam pl. céges adatokat), de az adat formátuma ami a provdereknek szükséges különböző. Jelen esetben nálam ez egy bazi nagy denormalizált excel tábla az egyik végen, a másik végen pedig egy EF model alapú adatbázis. A Sync Framework úgy tűnik, hogy mostantól lehetőséget ad arra, hogy implementáljunk interfaceket, melyek konvertálják az adatokat a providereknek megfelelő formátumba. Ez az adatkonverziós API lehet használt bármilyen típusú egyéni szinkronizációs providerrel, továbbá a Sync Framework tartalmaz konverziós API-t kimondottan a fájl szinkronizációs providerhez is. Change application service A Sync Framework (a korábbi CTP is) tartalmaz egy change applier implementációt, amit a legtöbb alkalmazás használ alkalmazni a változásokat egy replikára. A CTP2 viszont bevezeti a change application service-t, mely ugyanazokat a műveleteket teljesíti, mint a change applier, de sokkal testreszabhatóbb módon. Ha egy destination providernek szükséges nagyobb rugalmasság, mint az alap változás alkalmazó, lehetősége van használni a change application service-t, hogy teljesítse csak egy halmazát a szükséges műveleteknek. A telepítéssel kapcsolatban annyit még, hogy le kell szedni az előző CTP-ket előtte. A telepítő pedig innen letölthető: Microsoft Sync Framework 2.0 CTP2. Hajrá! June 01 Microsoft BingElindult a Microsoft új keresője, a Bing. Egyenlőre még az összes feature használatához szükséges US-re állítani az ország/régió beállításokat, illetve angolra a nyelvet, de ígéretesnek néz ki nagyon. Néhány hasznos dolog, amit kigyűjtöttem erről (a képeken pirossal részletezve vannak a figyelemre méltó újdonságok): itt. May 27 WPF - Model-View-ViewModel bevezetőA Microsoft azért adta ki az MVVM Toolkit-et, hogy egy egyszerűbb és jobban áttekinthető megoldást nyújtson minden WPF fejlesztő számára. Ez annyira igaz, hogy elvileg része lesz az eljövendő RTM verziónak, illetve a WPF 4.0 parancsrendszerét is megreformálják pont emiatt. Voltak páran akik megkértek mostanában, hogy meséljek erről az MVVM-ről néhány szót. Mivel ez a téma elég szerteágazó és kisezer megközelítés létezik, hozzávetőlegesen megpróbálom bemutatni a Microsoft-os WPF MVVM elképzelést, mely pont az egyszerűséget és könnyen érthetőséget hivatott megcélozni. Először is a lényege az MVVM-nek, akárcsak az ősének az MVC-nek, hogy szeparálja a kód logikát a felhasználói felülettől. Egy jól tervezett alkalmazás ismérve a könnyű fejleszthetőség, tesztelhetőség, illetve fenntarthatóság. Model ViewModel A sorrend nagyon fontos !
Haladjunk sorjában: Először is készítünk egy adatbázist. Ez egy egyszerű kis adatbázis, mindössze 1 táblát tartalmaz (Products) néhány mezővel, mint Name, Description, Price. Néhány tesztadatot érdemes felvenni bele. Jön a model réteg. Itt készítünk egy ProductData osztályt, ami a meglévő EF Product entitás osztályunkat fogja becsomagolni, illetve kibővíti azt más tulajdonságokkal. Ebbe a rétegbe visszük le a validációs logikát is. Minden adatot reprezentáló model osztály implementálja az INotifyPropertyChanged, illetve IDataErrorInfo interfészeket. Jelen esetben én ezt leegyszerűsítettem egy ObservableObject és ValidableObject segítségével. Ugyanitt kerül implementálásra a ProductBook osztály. Ez reprezentál egy terméklista manager osztályt. Ő már maga tárolja a becsomagolt termék objektumokat, de semmilyen állapotadatot nem tárol, mint pl. ki van kijelölve. Direkt NotificationCollection-be vannak téve a termék adatok, hogy ne függjön a kód a WPF-től. Ebbe az osztályba kerülnek megvalósításra az alapvető műveletek is, mint pl. új termékadat felvétele, egy termékadat törlése, illetve a módosítások mentése. ViewModel Itt alapvetően két darab ViewModel osztály létezik, az egyik a MainViewModel, a másik pedig a ProductBookViewModel. Készíthetnénk külön ViewModel osztályt magának a ProductData-nak is, de jelen esetben ez szükségtelen. Az annyit tenne mindössze, hogy magát a ProductData-t is becsomagolnánk egy ProductDataViewModel osztályba és ezt használnánk a ProductBookViewModel-ben, de ez nem szükséges, mivel a validáció a modelben van és nincs szükség bővíteni vizuális állapotinformációkkal ezt. Mint láthatjuk a kódban, a ProductBookViewModel konstruktora példányosítja a model (ProductBook) manager osztályt és feliratkozik annak a kollekciójának CollectionChanged eseményére, hogy diszpécselje a változásokat a model listájából a ViewModel ObservableCollection-be. Tehát magyarul szinkronban tartjuk a modellünk kollekcióját a view modellünk kollekciójával, ami már egy WPF specifikus kollekció (ObservableCollection), ugyanis ezt fogjuk bekötni a view objektumaink lista vezérlőibe, pontosabban ezeknek egy nézetét (CollectionViewSource). Tehát most ott tartunk, hogy a ViewModel-ünknek van egy példánya a hozzá tartozó modelből: röviden a ProductBookViewModel objektumunk ismeri a ProductBook model objektumot. Következő lépésben minden commandot kipakolunk ide. Azt, hogy épp ki van kijelölve a SelectedProductData tulajdonság határozza meg a ViewModel-be. Tehát a törlés parancsunk például így néz ki: View Ha megnézzük a ProductBookView.xaml fájlt máris megértünk mindent. Látható, hogy a lista control be van kötve a view model osztályunk megfelelő tulajdonságaiba. A kötésben az adatforrás ilyenkor a legközelebbi ráeső DataContext, mely jelen esetben a UserControl-unk DataContext-je lesz, ami ugye nem más lesz, mint egy ViewModel objektum. <ContentPresenter _logics = new Dictionary<LogicType, LogicTypePair>(); May 19 WPF konverterekKészítettem egy gyors módszert a konverterek használatához. Először is, ugye ahhoz, hogy konvertereket tudjunk használni mindig fel kell vennünk őket az erőforrások közé, majd StaticResource segítségével bekötni őket. Ezzel csak az a probléma, hogy egy idő után fárasztóvá válik a dolog. Tehát, az első akadályozó tényezőre a megoldás XAML markup extension-ök használata. Csinálunk először is egy generikus bázis osztályt, ami az összes konverterünk őse lesz markup támogatással: using System; using System.Globalization; using System.Windows.Markup; using System.Windows.Data; namespace VVMF.Core.WPF.Converters { [MarkupExtensionReturnType(typeof(IValueConverter))] public abstract class ConverterMarkupExtension<T> : MarkupExtension, IValueConverter where T: class, IValueConverter, new() { private static T _converter = null; public override object ProvideValue(IServiceProvider serviceProvider) { if (_converter == null) _converter = new T(); return _converter; } #region IValueConverter Members public abstract object Convert(object value, Type targetType, object parameter, CultureInfo culture); public abstract object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture); #endregion } } Ezt követően azért, hogy az értéktípusokat/nullázható típusokat is könnyedén tudjuk kezelni, készítettem egy egyszerű kis segédosztályt: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace VVMF.Core.WPF.Converters { public static class ConverterHelper { public static TValueType GetValue<TValueType>( object obj, TValueType defaultValue) where TValueType : struct { TValueType value = defaultValue; if (obj is TValueType) { value = (TValueType)obj; } else if (obj is TValueType?) { var nullable = (TValueType?)obj; value = nullable ?? defaultValue; } return value; } public static TValueType GetValue<TValueType>( object obj) where TValueType : struct { return GetValue<TValueType>(obj, default(TValueType)); } } } Majd tesztnek készítünk egy egyszerű kis szám inkrementáló konvertert: using System; using System.Windows.Data; using System.Globalization; namespace VVMF.Core.WPF.Converters { [ValueConversion(typeof(int), typeof(int))] public class IntegerIncrementerConverter : ConverterMarkupExtension<IntegerIncrementerConverter> { public override object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return ConverterHelper.GetValue<int>(value) + ConverterHelper.GetValue<int>(parameter, 1); } public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return ConverterHelper.GetValue<int>(value) - ConverterHelper.GetValue<int>(parameter, 1); } } } Ezután már XAML-be mindössze ennyit kell írnunk: <TextBlock Grid.Column="0" Text="{Binding SelectedIndex, Converter={coreconverters:IntegerIncrementerConverter}, Ehelyett: <UserControl.Resources> <coreconverters:IntegerIncrementerConverter <TextBlock Grid.Column="0" Text="{Binding SelectedIndex, Converter={StaticResource IntegerIncrementerConverter}, ElementName=dgOrganizations}" Margin="5"/> May 12 Delphi Prism májusi releaseA májusi kiadás már megpróbál bevezetni egy-két újdonságot még a .NET 4.0 és C# 4.0 előtt. Az új feature-k részletes leírása itt megtalálható. Ezen a listán szerepel a volatile fieldek, a generic type variance–ok, illetve újabb LINQ operátorok támogatása is, mint pl. skip, while, take és take while. May 08 WPF IntelliSense: hol volt, hol nem voltEgyes CTP-k telepítése után érhet bennünket meglepetés, mint pl. eltűnik a XAML IntelliSense a VS-ből. Mondanom sem kell, hogy nem éppen kellemes meglepetés volt a dolog. Mondom a megoldást máris:
May 07 Windows® API Code Pack for Microsoft® .NET Framework (v0.85)Érkeznek az utángyártott managelt könyvtárak a Windows 7 újdonságainak kihasználáshoz is többek között. Na meg persze a Vista olyan szolgáltatásaihoz is, melyekhez nem voltak managelt könyvtárak (lsd. DWM). Úgy látom, hogy mostanában ez a divat, akárcsak a Sync Framework esetében (minden megy natív kódba és arra húznak még egy managelt réteget). Letöltés itt. |
|
|||||||
|
|