Le scénario: Créer un MarkupExtension pour remplacer Grid.Row = » 0” par Grid.Row = » {espace de noms: ClassExtension GridRowName} »(même pour la colonne)résultats WPF MarkupExtension et RowDefinition à NotImplementedException
code XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" x:Name="TitleRow" />
<RowDefinition Height="Auto" x:Name="LastNameRow" />
<RowDefinition Height="Auto" x:Name="FirstNameRow" />
<RowDefinition Height="Auto" x:Name="EmailRow" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LabelColumn" />
<ColumnDefinition x:Name="ValueColumn" />
</Grid.ColumnDefinitions>
<Label Grid.Row="{me:GridDefinition Name=TitleRow}" Grid.ColumnSpan="2" FontWeight="Bold" FontSize="14" />
<Label Grid.Row="{me:GridDefinition Name=LastNameRow}" Grid.Column="{me:GridDefinition Name=LabelColumn}" FontWeight="Bold" FontSize="14" />
</Grid>
L'exigence:
- Afficher les erreurs XAML lorsqu'un GridRowName de incorrent (ou columnName) est utilisé
- Afficher aucune erreur XAML lorsqu'un GridRowName correct (ou columnName) est utilisé
- Lorsqu'un NomColonne valide est utilisé pour une déclaration de ligne (et Vica verca) une erreur de XAML doit être montré
Le problème: Tout fonctionne bien pour Grid.Column, mais grid.Row lance toujours un « Non implémenté Exception » à designtime (grid.row est souligné , grid.colu mn n'est pas).
Les lignes et colonnes sont toutes les deux nommées correctes, mais la ligne affiche toujours une erreur. Si nous spécifions un nom de colonne incorrect, la colonne affiche une erreur (qui devrait, si Grid.Column fonctionne très bien!)
Comme vous pouvez le voir, la colonne fonctionne très bien, mais les lignes ne le font pas. Le problème se trouve à l'intérieur du MarkupExtension appelé GridDefinitionExtension:
[MarkupExtensionReturnType(typeof(int))]
public class GridDefinitionExtension : MarkupExtension
{
public string Name { private get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
var referenceExt = new Reference(Name);
var definition = referenceExt.ProvideValue(serviceProvider);
if (definition is DefinitionBase)
{
var grid = (definition as FrameworkContentElement).Parent as Grid;
if (grid != null && definition is RowDefinition)
return grid.RowDefinitions.IndexOf(definition as RowDefinition);
if (grid != null && definition is ColumnDefinition)
return grid.ColumnDefinitions.IndexOf(definition as ColumnDefinition);
}
// This Extension only works for DefinitionBase Elements.
throw new NotSupportedException();
}
}
L'exception est trown sur la ligne:
var definition = referenceExt.ProvideValue(serviceProvider);
Après avoir regardé à l'intérieur de la DLL à partir de laquelle cette méthode est appelée, j'ai trouvé que le corps de cette méthode de ProvideValue ressemble à ceci:
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (serviceProvider == null)
throw new ArgumentNullException("serviceProvider");
IXamlNameResolver xamlNameResolver = serviceProvider.GetService(typeof (IXamlNameResolver)) as IXamlNameResolver;
if (xamlNameResolver == null)
throw new InvalidOperationException(System.Xaml.SR.Get("MissingNameResolver"));
if (string.IsNullOrEmpty(this.Name))
throw new InvalidOperationException(System.Xaml.SR.Get("MustHaveName"));
object obj = xamlNameResolver.Resolve(this.Name);
if (obj == null)
{
string[] strArray = new string[1]
{
this.Name
};
obj = xamlNameResolver.GetFixupToken((IEnumerable<string>) strArray, true);
}
return obj;
}
J'ai simplifié cette méthode de ProvideValue pour afficher uniquement le code qu'il i s en utilisant réellement dans mon scénario:
if (serviceProvider == null)
throw new ArgumentNullException("serviceProvider");
IXamlNameResolver xamlNameResolver = serviceProvider.GetService(typeof(IXamlNameResolver)) as IXamlNameResolver;
object obj = xamlNameResolver.Resolve(this.Name);
if (obj == null)
{
var strArray = new string[1]{ this.Name };
obj = xamlNameResolver.GetFixupToken((IEnumerable<string>)strArray, true);
}
return obj;
Apparantly l'exception est levée par la méthode GetFixUpToken, mais la cause est la méthode de Resolve. Cette méthode Resolve renvoie un objet valide lorsque vous recherchez la ColumnDefinition par son nom, mais elle renvoie NULL lorsque vous faites exactement la même chose pour une RowDefinition.
L'erreur lancée par GetFixUpToken est: « NotImplementedException », qui devrait depuis quand on regarde le code source du IXamlNameResolver (qui dans ce cas est de type: XamlNameResolverImpl)
Lorsque l'on regarde le code source de ce XamlNameResolverImpl, vous pouvez voir que la méthode « GetFixUpToken » est vide et renvoie une exception NotImplemented (regardez http://dotnetinside.com/en/framework/Microsoft+Expression/Microsoft.Expression.WpfPlatform/WpfMarkupExtensionValueSetter)
public object GetFixupToken(IEnumerable<string> names, bool canAssignDirectly)
{
throw new NotImplementedException();
}
public object GetFixupToken(IEnumerable<string> names)
{
throw new NotImplementedException();
}
Mais le problème est, comme je l'ai déjà dit, est l'appel de Resolve, qui fonctionne très bien pour ColumnDefinition mais échoue pour rowdefinitions ...:
Colonne:
Row:
À ce stade , je ne sais pas quoi faire ...
code source (exemple de projet) disponible à: http://www.frederikprijck.net/stuff/MarkupExtension.rar
Juste une recommandation. Utilisez le code actuel dans votre message (comme ce que vous avez fait avec le xaml) au lieu de captures d'écran du code. Certaines de ces captures d'écran sont assez petites lorsqu'elles sont redimensionnées dans SO. –
J'ai utilisé la capture d'écran parce que je voulais souligner tous les problèmes: Xaml Underline, valeurs d'exécution C#, ... Il y a quelques captures d'écran que j'ai remplacées par du code, puisque vous avez raison. Je suppose que j'ai commencé à utiliser des captures d'écran et j'ai oublié d'utiliser du texte si possible. Btw, j'ai ajouté le projet source pour ces raisons :-) –