Domanda

Attualmente sto creando un'applicazione che consiste di diversi componenti, ognuno dei quali è essenzialmente un controllo utente WPF con un po 'di codice C # attorno perché il sistema di plugin funzioni (usando MEF).

Il problema che sto riscontrando è che ogni componente dovrebbe includere un'icona e per motivi di gentilezza l'ho definito come System.Windows.Media.Brush in modo da poter semplicemente usare DrawingBrush esportato da Design lì. Ora ho bisogno di accedere a quel pezzo di XAML da un C # non WPF dove attualmente ho la terribile soluzione di istanziare il controllo utente e chiedergli la risorsa:

private Brush CachedIcon = null;

public override Brush Icon
{
    get
    {
        if (CachedIcon == null)
        {
            CachedIcon = (Brush)(new BlahControl().TryFindResource("Icon"));
        }
        return CachedIcon;
    }
}

Non sono riuscito a trovare un modo per leggere quella risorsa (che è un file .xaml e referenziato in un ResourceDictionary nel controllo personalizzato) da un " normale " Classe C #. Qualcosa appartenente a WPF ha quel bel metodo TryFindResource ma come fare altrimenti? Non voglio avere il file XAML con l'icona che si trova attorno non incorporata.

È stato utile?

Soluzione

Nel tuo codice XAML assicurati che la risorsa icona abbia l'opzione di compilazione impostata su " Resource " ;, quindi fai riferimento alla risorsa per renderla una risorsa statica xaml

<UserControl.Resources>
    <BitmapImage x:Key="icon1" UriSource="Resources/Icon1.ico" />
</UserControl.Resources>

Quindi nel tuo codice .Net 2.0 troverai la risorsa in " {xamlName} .g.resource " flusso

Codice di esempio che carica tutte le icone da una DLL xaml in un dizionario:

using System.IO;
using System.Reflection;
using System.Collections;
using System.Resources;

...

var icons = new Dictionary<String, Bitmap>();
var externalBaml = Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, "MyXaml.dll"));
Stream resourceStream = externalBaml.GetManifestResourceStream(externalBaml.GetName().Name + ".g.resources");
using (ResourceReader resourceReader = new ResourceReader(resourceStream)) {
    foreach (DictionaryEntry resourceEntry in resourceReader) {
        if (resourceEntry.Key.ToString().ToUpper().EndsWith(".ICO")) {
            icons.Add(resourceEntry.Key.ToString(), Image.FromStream(resourceEntry.Value as Stream) as Bitmap);
        }
    }
}

Altri suggerimenti

I miei suggerimenti sono:

  • Fornisci metadati sul tuo controllo su dove si trova l'icona. Puoi farlo con il tuo attributo personalizzato (vedi esempio 1 di seguito). Questi metadati ti permetteranno di caricare l'icona senza creare un'istanza del controllo.

  • Dato che stai utilizzando MEF, puoi utilizzare i metadati nell'esportazione per ottenere lo stesso risultato di cui sopra. Dettagli qui . Vedi l'esempio 2 di seguito.

  • Tratta la tua icona come un ImageSource piuttosto che un Brush . Puoi usare il controllo Image di WPF per mostrare il tuo ImageSource , oppure puoi dipingerlo con un ImageBrush.

  • Utilizzare la tecnica fornita da TFD per leggere la risorsa con il nome specificato nei metadati. Sfortunatamente, WPF non sembra fornire nulla di simile a un BamlReader , il che renderebbe molto più pulito il caricamento della risorsa WPF da un contesto non WPF.

Esempio 1:

[Icon("MyIconResourceName")]
public class BlahControl : Control
{
    ...
}

Esempio 2:

[Export(typeof(IApplicationComponent))]
[ExportMetadata("IconResource", "MyIconResourceName")]
public class BlahControl : Control
{
    ...
}

Puoi leggere le risorse dal tuo assembly come stream.

Codice di esempio qui: http://www.wpftutorial.net/ReadWPFResourcesFromWinForms.html

Definisci le icone a livello di app anziché nel controllo, nel file xaml del dizionario delle risorse master o app.xaml. Quindi puoi utilizzare lo stesso metodo TryFindResource, ma senza creare un'istanza del controllo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top