Xamarin.Forms: Use converters with binding objects which can have null as value.

You have a converter, which should return a specific value, even if the binded object is null.

Converters does not get executed, when the binded value is null. But here is a solution, how to handle this situations.

Define an example converter

In this case we will use an Int value to bool value converter.

    public class IsIntGreaterThanConverter : IValueConverter, IMarkupExtension
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is int bindedValue && parameter is int targetValue)
            {
                return bindedValue > targetValue;
            }
            else
                return false;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        public object ProvideValue(IServiceProvider serviceProvider)
        {
            return this;
        }
    }

This code returns true, if the binded value is greater than the value provided as a converter parameter.

It can be used with the following code snippet in XAML:

            <Label Text="The value is greater than 0">
                <Label.IsVisible>
                    <Binding Path="Object.IntValue"
                             Converter="{app1:IsIntGreaterThanConverter}">
                        <Binding.ConverterParameter>
                            <x:Int32>0</x:Int32> 
                        </Binding.ConverterParameter>
                    </Binding>
                </Label.IsVisible>
            </Label>

But what happends, when the ‘Object’ is null? Well the converter does not get executed. And since View’s default value of the IsVisible bindable property is true, then the label will be visible, even if the Object is null.

How to handle null scenarios?

Bindings have a property called FallbackValue. Give a value to the fallbackvalue property in order to override the default value, like this:

           <Label Text="The value is greater than 0">
                <Label.IsVisible>
                    <Binding Path="Object.IntValue"

                             FallbackValue="False"

                             Converter="{app1:IsIntGreaterThanConverter}">
                        <Binding.ConverterParameter>
                            <x:Int32>0</x:Int32> 
                        </Binding.ConverterParameter>
                    </Binding>
                </Label.IsVisible>
            </Label>

This should return false even if the binded obejct is null. 🙂

This content has 2 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

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.

This content has 5 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

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)

 

This content has 5 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.