if(true) else ágba futásának története

Először nem hittem a szememnek, amikor megláttam..

A fenti példa szemlélteti, hogy két megegyező típusú, és megegyező értékű enum a debug folyamat során quick watchban egyenlőségvizsgálatnál igazra értékelődik ki, de mégis az else ágba fut a debug folyamatban lévő kód tovább.

A fenti videón látható részlet egy XAML converter létrehozásánál keletkezett, ahol az egyenlőségvizsgálat egy boolean értékkel kellett hogy visszatérjen. A feladat az volt, hogyha a ViewModellen található UIMode property értéke egy meghatározott értéket vesz fel, akkor a láthatósága bizonyos kontrolloknak ennek megfelelően állítódjon.
Jó ötletnek tűnt persze, hogy Convertert írunk a Bindable propertyre, ami paraméterben megkapja x:Static-kal, hogy milyen értéknek kell megfelelnie.

Jött a megvalósítás, a rutinfeladat, hiszen nem ez az első converter amit pályafutásom alatt már megírtam, hittem én. Majd szembesültem a ténnyel, hogy az az újonnan kitalált funkció integráció utáni tesztelési folyamatában közel sem úgy működik a dolog, ahogy azt elterveztem.

Ilyenkor persze jönnek a szokásos gyógyegér dologra való rámondásos orvoslásoknak tűnő dolgok: Clean solution, app törtlés mobilról, majd miután ez sikertelen, azután Force clean solution (ez a bin/debug obj/debug mappák fizikai törlését jelenti), VS restart, majd végül gép restart, de egyik sem hozott eredményt.

A probléma forrása (Ha gondolkozni szeretnél még azon, hogy mi lehetett a baj, ne olvasd tovább! 🙂 )

Magának az újonnan létrehozott Converternek, hogy használható legyen konverterként, az IValueConverterből kellett származnia, amely megköveteli, a Convert, és ConvertBack metódusok implementációját. Mivel ezeknek a metódusoknak a szignatúrája objectként várja át a value-t, és a paramétert, ezért az érték típusú változók boxingolódnak.

Mivel runtime az object equals fut meg rájuk, hamisra fog kiértékelődni a condition, és ezért esik az else ágba a kód.

Hogy a Visual Studio a debug folyamat során a watchban hogyan jön rá arra, hogy mégsem az object equalst kéne rajtuk végrahjtani, nem jártam utána, ettől függetlenül is kissé idegtépő volt a dolog.

Windows: “Leírás nélküli hiba történt”

“Leírás nélküli hiba történt” mondják a Magyar Windows Server 2008-tól felfelé található verziói, felhasználó hozzáadásánál.

A probléma előidézése a következőképpen: Szerveren megnyitjuk a Számítógép kezelést, azon belül a Felhasználók és Csoportok lapon a Felhasználóknál új felhasználót szeretnénk felvinni, akinek a jelszava soha nem jár le, és a felhasználó nem módosíthatja a jelszót (Ezeknek a variációját nem próbáltam,  de ebben az esetben mindenképpen találkozunk a problémával.)

Amennyiben a jelszó túl könnyűnek számít, az adminisztrátor abban az esetben találkozik a fent említett hibaüzenettel.

A Windows csoportházirendében van egy Password policiryre vonatkozó beállítás, amellyel engedélyezhetjük a könnyű jelszavak használatát, de ennek állítása nem ajánlott, főleg kiszolgálókon.

Ajánlott megoldás: Válasszunk egy erős jelszót, amelyben kis- nagybetűk szerepelnek, számokkal együtt, és legalább 8 karakter hosszúak.

Xamarin Forms: Ismerkedés a CustomUserControllokkal

Aki a Xamarin fejlesztésben kipróbálta magát, az könnyen találkozhatott azzal a problémával hogy valamit nem tud megvalósítani, mert nem ad rá a rendszer kész usercontrolt.

Prológus:


Nem rég azzal a problémával szembesültem, hogy a Xamarin Formsban elérhető ListView-nak a ContextActions menüjének láthatósága nem szabályozható. A ContextActions menu egy ListView elem hosszan nyomására jelenik meg. Ez tulajdonképpen egy lista MenuItem objektumokból. Ennek segítségével indíthatunk Commandokat a kiválasztott ListView elemét továbbadva. Azonban felmerülhet olyan igény, hogy szabályozhatóvá tehessük a hosszan nyomásra előtűnő menünk láthatóságát. Erre sajnos nincs lehetőségünk, csak különféle workaroundokkal. Rengeteg utánakeresés után arra jutottam, hogy a DataTemplate gyerekének, a ViewCell-nek az IsEnabled tulajdonsága tulajdonképpen letiltja a hosszan nyomást. Ez működött, adatköthettem a ViewModel-ben szereplő UI mód tulajdonságra, így a ContextMenü már csak akkor jelent meg, ha a UI mód szerkesztés módra volt állítva, megtekintés módon természetesen nem voltak elérhetőek a ContextMenüben szereplő adatmanipuláló gombok. És ekkor jött az igény. Mégpedig az, hogy szerkesztés módban jöjjenek elő az adatmanipuláló gombok, emellett megtekintés módban az elemre kattintva hajtódjon végre egy másik parancs. Erre gondoltam azt, hogy a SelectedItem tulajdonságnak Setter ága tökéletes lessz számomra. Mivel a ViewCell IsEnabledje megtekintés módban false volt, ezért a SelectedItem sem állítódott rajta. Az igény viszont az, hogy megtekintés módban csak a ContextMenü ne legyen elérhető, a lista elemre való kattintás viszont igen. Csak időközben felmerült még egy probléma: Ameddig a lista tartalmát nem frissítettem, addig a ContextMenü egy gombjára kattintva a Commandnak átadott paraméter null volt, és nem a ListView hosszan nyomott eleme. Ezek együttese igencsak nagy problémának tűnt számomra. Aztán rászántam magam a megoldására: A turbósított usercontrol fejlesztésére.

Megoldás:
Először azt szerettem volna megoldani, hogy ne a SelectedItem setter ágában kelljen végrehajtanom azt a logikát, amit akkor kell futtatnom, amikor a felhasználó rányom egy elemre. Továbbá a SelectedItem nem változik meg, ha a felhasználó ugyanarra az elemre nyom a listában. Leszármaztattam egy “ExtendedListView-t” a ListView osztályból. Új controlom konstruktorában feliratkoztam az ősosztály ItemTapped eseményére. Létrehoztam egy Bindolható Propertyt, ami várja azt a parancsot, amelyet végre kell majd hajtania. Az ItemTapped eseménykezelőjében pedig a szükséges vizsgálatok után megfuttatom a Commandot. Ezzel a felhasználó kétszer is rányomhat ugyanarra az elemre.

A másik nehezebb dolog a ContextActions menü eltüntetése volt. Tudtam, ha a ContextActions listája üres, hosszan nyomására nem jelenik meg semmi. Ha legalább egy elem van benne, akkor már megjelenik. Leszármaztam egy ViewCell objektumból. Létrehoztam egy ContextActionsEnabled bindolható tulajdonságot. Ennek a tulajdonságnak változására iratkoztam fel egy eseménykezelővel. Létrehoztam egy privát field-et, ami MenuItem-eket tárol. Sajnos nem találtam a Xamarinban a WPF-hez hasonló Initalized eseményt, így nem tudtam arra feliratkozni, hogy a Control beállítódott. Ez azért volt probléma, mert a tervem az volt, hogy XAML-ben definiálom hogy milyen MenuItemek vannak a ContextActionsben, majd amint a Control befejezte a beállítódását, eltárolom a MenuItemeket, a privát fieldemben. Így csak a ContextActionsEnabled változására kellett volna egy eseménykezelést írnom. Amennyiben a ContextActionsEnabled true értéket kap, abban az esetben beleteszem az ősosztály ContextActions tulajdonságába a fieldemben tárolt MenuItemeket, amennyiben false értéket kap, abban az esetben pedig eltávolítom az összeset ami benne van (az ősosztály ContextActions tulajdonságában). Mivel nem volt Initalized esemény, kénytelen voltam a ContextActionsEnabled megváltozásának eseménykezelőjébe beletenni azt, hogy első alkalommal tárolja el a field-be az eredeti XAML-ben definiált értékeket. Ez azt eredméynezi, hogy ha előbb definiáljuk XAML-ben a ContextActionsEnabled Propertyt, mint magát a ContextActions-t, nem fog működni. Erre még jó lenne egy jobb megoldást hallani. Ha van rá ötleted, kérlek jelezd azt kommentben!


Nem jártam utána, de miután a ViewCell IsEnabledjéről lekerült a Bindolás, a ContextMenü commandjai már soha többé nem kaptak null értéket.

Xamarin Forms: XAML hibák feltárása

Aki ismerkedett a Xamarin Forms-szal, bizonyára észrevette, hogy a XAML fájl futásidőben értékelődik ki. Ez fejlesztés közben hatalmas hátrányt jelent a fejlesztő számára, hiszen egy hibásan megírt XAML fájl csak a debug folyamat közben bukik ki.

A szintaktikailag hibás fájl

Emiatt szükség volt egy megoldásra, annak érdekében, hogy a fordítási időben kapjunk hibát a szintaktikailag nem helyes kódról.

A XAML Compilation azonnal köztes nyelvre fordítja a felületet leíró fájlokat. Erről a továbbiakban itt olvashatsz: https://developer.xamarin.com/guides/xamarin-forms/xaml/xamlc/

[assembly: XamlCompilation (XamlCompilationOptions.Compile)]

Valami nem klappol!

Az attribútum használata az app.xaml.cs-ben a namespace-en attribútumként:

 

(Archived post from: 2017.08.12)

 

Xamarin Forms: Nem fordul az újonnan létrehozott solution androidos projektje

Prológus:

A cégnél elsők között lehettem, akik a Xamarin fejlesztés rejtelmeibe áshatták bele magukat. Hogy megelőzzek más fejlesztőknek akár órás fejfájásokat, írásba öntöm tapasztalataimat.

Tézis:
Az újonnan létrehozott Xamarin Forms Solution Androidos projektjének futtatásánál a hasonló hibaüzenetekkel találkozhatunk:

Hibaüzenetek a friss projektnél

A Solution NuGet Csomagjait vizsgáljuk meg először.

Vegyük szemügyre a Xamarin.Forms nevű csomagot, egész pontosan annak a Dependencies résznél található csomagok verzió igényeit.

Xamarin Forms package Dependencies

Láthatjuk, hogy (például) a Xamarin.Android.Support.Design csomag verziószámának meg kell egyezni a 23.3.0 verzióval. Gyanakodhatunk arra, hogy eltérő csomag verziók vannak telepítve. A Xamarin.Android.Support.Design csomag nevére kattintva pedig meggyőződhetünk erről.

A nem megfelelő csomag van telepítve

Frissítsük a NuGet package-t a helyes verzióra. Ellenőrizzük az összes csomagot, majd futtassuk az Androidos projektet.

 

(Archive post from 2017.08.12)