c# - supported - mvvmcross xamarin forms
MvvmCross ViewTypeResolver no resuelve Tag(fragmento o tipo personalizado) (1)
La situación real es que agregué a la clase MvxViewTypeResolver
el "Fragmento" -Case, por lo que se ve así:
#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(".");
}
}
}
Ahora está enviando el longLowerCaseTagName
correcto (android.app.fragment) pero en la consulta no puede resolver el tipo.
Mi sugerencia es que el control de fragmentos no se cargue cuando se debe resolver el tipo. Tal vez hay otra forma de resolver el tipo?
Además, si agrego un tipo personalizado (dando la etiqueta Mvx.MyCustomType
en el axml) no se resuelve. ¿Debo agregar algo en MvxBindingAttributes.xml
en este caso?
¡Gracias por la ayuda!
Primero una explicación del código:
La fábrica personalizada de inflables XML utilizada por MvvmCross Binder intenta cargar Views de una manera muy similar al 2.x estándar Android.
El código predeterminado para la resolución del tipo de vista está en: https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross.Binding/Android/Binders/MvxViewTypeResolver.cs
Si su xml contiene un nombre como <MyCompany.MyProject.MyViews.MyFirstView />
entonces el tipo de resolución de la vista:
primero busca abreviaturas y las expande en espacios de nombres completos; de manera predeterminada, la única abreviatura conocida es
Mvx.
que se expande a:Cirrious.MvvmCross.Binding.Android.Views.
. Si desea agregar más abreviaciones, entonces anuleViewNamespaceAbbreviations
en https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross.Binding/Android/MvxBaseAndroidBindingSetup.csluego verifica si el nombre no abreviado es un nombre sin nombre de espacio. Si es así, se supone que la clase es el espacio de nombre de Android y lo precede con
android.view.
oandroid.widget.
luego convierte el nombre del espacio de nombres completo en minúsculas como una clave de búsqueda insensible a mayúsculas y minúsculas
usa esa tecla minúscula para buscar todos los tipos que se derivan de la vista en todos los conjuntos cargados.
almacena en caché el resultado (ya sea nulo o no) para acelerar las inflaciones posteriores.
Todo este comportamiento se diseñó para coincidir con el código de inflación de la vista de Android xml predeterminado en 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
Con esa explicación fuera del camino, he aquí una respuesta a sus preguntas:
MvvmCross aún no contiene ningún soporte de Fragment. El soporte oficial del fragmento MonoDroid en sí mismo fue lanzado la semana pasada, y todavía no he tenido fragmentos de solicitud: la "fragmentación" de Android parece haber mantenido a la mayoría de la gente en el código basado en Dialog y Activity.
En pocas palabras, al examinar la documentación, el fragment
no es una vista de Android, parece que Fragment hereda directamente de Java.Lang.Object, consulte http://developer.android.com/reference/android/app/Fragment.html.
Debido a esto, no hay forma de que MvvmCross ViewTypeResolver funcione actualmente con fragmentos.
Sugeriría que si necesitas mvvmcross y fragmentos hoy, tu mejor opción es reemplazar la resolución predeterminada (usando IoC) con tu propia resolución, pero no puedo ofrecer muchos consejos sobre esto ya que aún no he leído por completo y entendió los documentos de droides en http://developer.android.com/guide/topics/fundamentals/fragments.html
Según mi experiencia en la creación del código de inflación actual, creo que encontrará la fuente de lectura esencial cuando lo haga, por ejemplo, consulte: 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
No puedo darle ninguna información sobre cuándo estará disponible el soporte oficial de fragmento mvvmcross, no es algo que esté actualmente programado.
Las vistas personalizadas son compatibles, pero normalmente no vivirán en el Mvx.
abreviado espacio de nombres.
Es mucho más probable que vivan en el espacio de nombres de su aplicación de interfaz de usuario, o en alguna biblioteca compartida.
Para ver una vista personalizada en acción, consulte el ejemplo PullToRefresh en el tutorial - https://github.com/slodge/MvvmCross/blob/master/Sample%20-%20Tutorial/Tutorial/Tutorial.UI.Droid/Resources/Layout /Page_PullToRefreshView.axml