MvvmCross ViewTypeResolver ne permet pas de résoudre Tag (fragment ou de type personnalisé)

StackOverflow https://stackoverflow.com//questions/10698638

  •  12-12-2019
  •  | 
  •  

Question

Situation réelle est, que j'ai ajouté à la MvxViewTypeResolver classe le "Fragment"-Cas, de sorte qu'il ne ressemble à ceci:

 #region Copyright
// <copyright file="MvxViewTypeResolver.cs" company="Cirrious">
// (c) Copyright Cirrious. http://www.cirrious.com
// This source is subject to the Microsoft Public License (Ms-PL)
// Please see license.txt on http://opensource.org/licenses/ms-pl.html
// All other rights reserved.
// </copyright>
// 
// Project Lead - Stuart Lodge, Cirrious. http://www.cirrious.com
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.Views;
using Cirrious.MvvmCross.Binding.Android.Interfaces.Binders;

namespace Cirrious.MvvmCross.Binding.Android.Binders
{
    public class MvxViewTypeResolver : IMvxViewTypeResolver
    {
        private Dictionary<string, Type> _cache = new Dictionary<string, Type>();

        public IDictionary<string, string> ViewNamespaceAbbreviations { get; set; }

        #region IMvxViewTypeResolver Members

        public virtual Type Resolve(string tagName)
        {
            Type toReturn;
            if (_cache.TryGetValue(tagName, out toReturn))
                return toReturn;

            var unabbreviatedTagName = UnabbreviateTagName(tagName);

            var longLowerCaseName = GetLookupName(unabbreviatedTagName);
            var viewType = typeof(View);

#warning AppDomain.CurrentDomain.GetAssemblies is only the loaded assemblies - so we might miss controls if not already loaded
            var query = from assembly in AppDomain.CurrentDomain.GetAssemblies()
                        from type in assembly.GetTypes()
                        where viewType.IsAssignableFrom(type)
                        where (type.FullName ?? "-").ToLowerInvariant() == longLowerCaseName
                        select type;

            toReturn = query.FirstOrDefault();
            _cache[tagName] = toReturn;

            return toReturn;
        }

        private string UnabbreviateTagName(string tagName)
        {
            var filteredTagName = tagName;
            if (ViewNamespaceAbbreviations != null)
            {
                var split = tagName.Split(new char[] {'.'}, 2, StringSplitOptions.RemoveEmptyEntries);
                if (split.Length == 2)
                {
                    var abbreviate = split[0];
                    string fullName;
                    if (ViewNamespaceAbbreviations.TryGetValue(abbreviate, out fullName))
                    {
                        filteredTagName = fullName + "." + split[1];
                    }
                }
            }
            return filteredTagName;
        }

        #endregion

        protected string GetLookupName(string tagName)
        {
            var nameBuilder = new StringBuilder();

            switch (tagName)
            {
                case "View":
                case "ViewGroup":
                    nameBuilder.Append("android.view.");
                    break;
                case "fragment":
                    nameBuilder.Append("android.app.");
                    break;
                default:
                    if (!IsFullyQualified(tagName))
                        nameBuilder.Append("android.widget.");
                    break;
            }

            nameBuilder.Append(tagName);
            return nameBuilder.ToString().ToLowerInvariant();
        }

        private static bool IsFullyQualified(string tagName)
        {
            return tagName.Contains(".");
        }
    }
}

Maintenant, c'est la soumission de la bonne longLowerCaseTagName (android.app.fragment), mais dans la requête, il n'est pas en mesure de résoudre le type.

Ma suggestion est que le fragment de contrôle n'est pas chargé lorsque le type doit être résolu.Peut-être il ya une autre façon d'obtenir le type résolu?

Aussi, si j'ajoute un type personnalisé (en donnant la balise Mvx.MyCustomType dans le axml) qu'il ne soit pas résolu.Dois-je ajouter quelque chose dans la MvxBindingAttributes.xml dans ce cas?

Merci pour l'aide!

Était-ce utile?

La solution

D'abord une explication du code:

Le custom XML inflater usine utilisée par le MvvmCross Liant essaie de charger les points de Vue dans une manière très semblable à la norme 2.x Android XML inflater.

Le code par défaut pour le type d'affichage résolution est en effet en: https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross.Binding/Android/Binders/MvxViewTypeResolver.cs

Si votre xml contient un nom tel que <MyCompany.MyProject.MyViews.MyFirstView /> le point de vue du type de résolution:

  • vérifie d'abord pour les abréviations et se développe en pleine espaces de noms par défaut, la seule connue abréviation est Mvx. qui est développé à: Cirrious.MvvmCross.Binding.Android.Views..Si vous voulez ajouter plus de abbrevations ensuite remplacer l' ViewNamespaceAbbreviations dans https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross.Binding/Android/MvxBaseAndroidBindingSetup.cs

  • puis vérifie si le non abrégé, le nom est un non-des espaces de nom.Si c'est le cas, il suppose que la classe est le Android de l'espace de noms et la positionne en tête avec android.view. ou android.widget.

  • puis convertit le pleinement des espaces de nom en minuscules comme un cas insensibles à la recherche de la clé

  • utilise cette minuscule clé pour rechercher tous les Types qui tirent hors de la Vue dans tous les assemblys chargés.

  • met en cache le résultat (si sa valeur null ou pas) afin d'accélérer ultérieure inflations.

L'ensemble de ce comportement a été conçu pour correspondre à la valeur par défaut d'Android xml de vue de l'inflation dans le code http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.6_r1/android/view/LayoutInflater.java#LayoutInflater.createViewFromTag%28java.lang.String%2Candroid.util.AttributeSet%29


Avec cette explication de la façon dont - voici une réponse à vos questions:


MvvmCross n'a pas encore actuellement contenir tout Fragment de soutien.L'officiel MonoDroid fragment de support lui-même n'a été publié la semaine dernière, et je n'ai pas encore eu quelqu'un demande des fragments - Android "fragmentation" semble avoir gardé la plupart des gens de retour sur l'Activité et la boîte de Dialogue basée sur le code.

Brièvement ;ooking à la documentation, fragment n'est-ce pas un Androïde Vue, il ressemble Fragment hérite directement de Java.Lang.Objet - voir http://developer.android.com/reference/android/app/Fragment.html

De ce fait, il n'ya aucun moyen que le MvvmCross ViewTypeResolver actuellement travailler avec des fragments.

Je dirais que si vous avez besoin de mvvmcross et des fragments d'aujourd'hui, alors votre meilleur pari est de remplacer la valeur par défaut du résolveur (à l'aide du Cio) avec votre propre résolveur - mais je ne peux pas offrir beaucoup de conseils sur ce que je n'ai pas encore entièrement lu et compris le droid docs sur http://developer.android.com/guide/topics/fundamentals/fragments.html

De par mon expérience dans la création de l'inflation actuelle du code, alors je pense que vous trouverez la source essentielle de la lecture lorsque vous faites cela - par exemplevoir : http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/view/LayoutInflater.java#LayoutInflater.createViewFromTag%28android.view.View%2Cjava.lang.String%2Candroid.util.AttributeSet%29

Je ne peux pas vous donner d'informations sur quand officiel de mvvmcross fragment de soutien seront disponibles ce n'est pas quelque chose qui est actuellement prévu.


Les vues personnalisées sont pris en charge, mais ne vivent normalement dans les Mvx. abrégé de l'espace de noms.

Ils sont beaucoup plus susceptibles de vivre dans votre INTERFACE utilisateur d'application de l'espace de noms, ou dans une bibliothèque partagée.

Pour voir un affichage personnalisé en action, voir la PullToRefresh exemple dans le tutoriel: - https://github.com/slodge/MvvmCross/blob/master/Sample%20-%20Tutorial/Tutorial/Tutorial.UI.Droid/Resources/Layout/Page_PullToRefreshView.axml

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top