2009-06-29 3 views
1

J'ai des classes personnalisées que j'instancie actuellement dans App.xaml en tant que ressources. Je veux déplacer ces objets personnalisés dans un ResourceDictionary fusionné, où ils sont utilisés dans les styles, et les garder près de l'endroit où ils sont utilisés. Voici un exemple de ce que je veux, en utilisant arbitrairement des objets de conversion faux, mais ils pourraient être un objet personnalisé ...Silverlight 3 - Création d'objets personnalisés dans un ResourceDictionary fusionné

App.xaml (déclarations d'espace de noms omises):

<Application.Resources> 
<ResourceDictionary> 
    <ResourceDictionary.MergedDictionaries> 
     <ResourceDictionary Source="Merged.xaml" /> 
    </ResourceDictionary.MergedDictionaries> 
    <Style x:Key="SomeStyle" TargetType="SomeControl"> 
     ... 
    </Style> 
    ... 

</ResourceDictionary> 

Et puis dans Merged.xaml (déclarations d'espace de noms omis):

<ResourceDictionary> 
    <cvt:VisibilityToBoolConverter x:Key="BoolToVisibility" Inverted="True"/> 
    <cvt:VisibilityToBoolConverter x:Key="NotBoolToVisibility" Inverted="True" Not="True"/> 

    <Style x:Key="SomethingThatUsesVisibilityToBoolConvertersStyle" TargetType="SomeOtherControl"> 
     .... 
    </Style> 
</ResourceDictionary> 

la question que je vois est la suivante: quand je crée le BoolToVisibility et non Les objets BoolToVisibility (ainsi que l'instanciation d'autres objets qui sont des instances de classes personnalisées que j'ai créées) tout comme une partie Application.Resources, ils sont créés et toutes les références fonctionnent comme prévu; cependant, lorsque je les déplace dans un dictionnaire de ressources fusionné (comme dans l'exemple ci-dessus), j'obtiens une exception d'application malformée lors du chargement de l'application Silverlight. Je crois que c'est un problème avec la manière dont les objets sont instanciés différemment dans les Dictionnaires de ressources fusionnés (je crois qu'il s'agit plutôt d'une approche de chargement paresseux), mais je m'attendrais à ce que cela fonctionne néanmoins.

Je suis très capable d'ajouter des objets Style, DataTemplates, ControlTemplates et autres. Mais quand je veux créer des instances de classes personnalisées qui sont nommées ou saisies en utilisant Xaml, cela fonctionne très bien dans Application.Resources de App.xaml directement et Application.Resources/ResourceDictionary aussi. Dès qu'ils sont déplacés dans un dictionnaire fusionné, il lève l'exception. Est-ce par conception? D'autres idées qui fonctionnent? Merci d'avance ...

Répondre

0

J'ai finalement travaillé autour de cela. J'ai pris une page sur la façon dont la classe App est instanciée et fait la même chose avec le fichier Merged.xaml. J'ai créé une classe avec "code-behind" pour Merged.xaml, appelé Merged qui hérite de ResourceDictionary. Je puis (en empruntant à App.g.cs), j'initialiser le composant en chargeant à partir du fichier Merged.xaml pendant la construction.

Merged.xaml.cs:

public partial class Merged : ResourceDictionary 
{ 
    private bool _contentLoaded; 

    public Merged() 
    { 
     InitializeComponent(); 
    } 

    public void InitializeComponent() 
    { 
     if (_contentLoaded) 
     { 
      return; 
     } 
     _contentLoaded = true; 
     System.Windows.Application.LoadComponent(this, new System.Uri("/MySilverlightApp;component/Merged.xaml", System.UriKind.Relative)); 
    } 
} 

Le fichier Merged.xaml ressemble exactement la même chose que dans ma question initiale, en utilisant ResourceDictionary comme il est l'élément racine.
L'App.xaml est légèrement différent. Au lieu de référencer la ResourceDictionary Fusionné en utilisant l'élément ResourceDictionary et l'attribut source, j'ai simplement fait référence à la classe Fusionné:

<Application.Resources 
xmlns:msa="clr-namespace:MySilverlightApplication"> 
<ResourceDictionary> 
    <ResourceDictionary.MergedDictionaries> 
     <msa:Merged /> 
    </ResourceDictionary.MergedDictionaries> 
    <Style x:Key="SomeStyle" TargetType="SomeControl"> 
     ... 
    </Style> 
    ... 
</ResourceDictionary> 
</Application.Resources> 

Viola! Ça marche.

0

Vous pouvez éviter le surcroît de code en définissant l'action de construction de votre xaml partagé sur "Resource" et en le référençant comme /AssemblyName;component/Shared.xaml. Pour une raison qui m'échappe le plus souvent, le fait de le référencer de cette manière permet à l'instanciation d'objet personnalisée de fonctionner correctement.