Come posso ottenere la directory dell'applicazione dalla mia applicazione WPF, in fase di progettazione?

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

Domanda

Come posso ottenere la directory dell'applicazione dalla mia applicazione WPF, in fase di progettazione? Ho bisogno di accedere a una risorsa nella directory corrente della mia applicazione in fase di progettazione, mentre il mio XAML viene visualizzato nella finestra di progettazione . Non sono in grado di utilizzare la soluzione specificata in questa domanda al momento della progettazione sia System.IO.Path.GetDirectoryName (Process.GetCurrentProcess (). MainModule.FileName) sia System.Reflection.Assembly.GetExecutingAssembly (). Posizione punta alla posizione dell'IDE (Visual Studio ... Common7 o qualcosa del genere).

Su richiesta per chiarire ulteriormente i miei obiettivi: desidero accedere a una tabella del database in fase di progettazione e visualizzare un grafico di tali dati. Il design è fatto in Visual Studio 2008, quindi quello di cui ho bisogno è una soluzione molto specifica per un problema molto specifico, e che sta ottenendo la directory di assemblaggio per la mia app.

È stato utile?

Soluzione

Dalla tua descrizione sembra che il tuo codice sia effettivamente in esecuzione all'interno del Designer WPF in Visual Studio, ad esempio fa parte di una libreria di controllo personalizzata che viene utilizzata per la progettazione.

In questo caso, Assembly.GetEntryAssembly () restituisce null, ma il seguente codice ottiene il percorso della directory dell'applicazione:

  string applicationDirectory = (
    from assembly in AppDomain.CurrentDomain.GetAssemblies()
    where assembly.CodeBase.EndsWith(".exe")
    select System.IO.Path.GetDirectoryName(assembly.CodeBase.Replace("file:///", ""))
    ).FirstOrDefault();

I seguenti passaggi possono essere utilizzati per dimostrare che funziona all'interno dello strumento WPF Designer di VS.NET 2008:

  1. Inserisci questo codice in una "Libreria di controllo personalizzato WPF" o " Libreria di classi " progetto
  2. Aggiungi il codice necessario per leggere il database e restituire i dati per la visualizzazione (nel mio caso ho appena restituito la directory dell'applicazione stessa come stringa)
  3. Fai riferimento al progetto della biblioteca dal progetto che stai progettando
  4. Utilizzare i controlli o le classi personalizzati da un file XAML per popolare DataContext o altrimenti fornire dati all'interfaccia utente (nel mio caso ho associato DataContext utilizzando x: Static)
  5. Modifica quel file XAML con " Windows Presentation Foundation Designer " ;, che può essere fatto semplicemente facendo doppio clic a meno che tu non abbia modificato il tuo editor predefinito, nel qual caso usa " Apri con ... "

Quando segui questi passaggi, l'oggetto che stai guardando verrà popolato con i dati dal tuo database allo stesso modo sia in fase di esecuzione che in fase di progettazione.

Ci sono altri scenari in cui questa stessa tecnica funziona altrettanto bene e ci sono altre soluzioni disponibili a seconda delle tue esigenze. Fateci sapere se le vostre esigenze sono diverse da quelle che ho assunto sopra. Ad esempio, se stai scrivendo un componente aggiuntivo VS.NET, ti trovi in ??un gioco con la palla completamente diverso.

Altri suggerimenti

Stai cercando di supportare un designer (come il designer di Visual Studio o Blend)?

In tal caso, esistono diversi modi per affrontare questo problema. In genere non si desidera fare affidamento su un percorso relativo dall'eseguibile perché può essere ospitato in diversi strumenti di progettazione (VS, Expression Blend ecc.)

Forse puoi spiegare in modo più completo il problema che stai cercando di risolvere in modo da poter fornire una risposta migliore?

Non credo sia possibile: stai chiedendo la posizione di un assieme che potenzialmente non è stato ancora costruito. Il codice in fase di progettazione non viene eseguito all'interno dell'applicazione e dovrebbe fare alcune ipotesi sull'IDE. Questo mi sembra sbagliato e fragile - considera queste domande:

  • Il progetto è stato ancora realizzato?
  • Altrimenti, non esiste un eseguibile per ottenere il percorso, e allora?
  • Sarebbero presenti gli altri file se non sono stati creati, o sono manufatti?
  • Se è stato costruito, dove è stato costruito?
  • Devi considerare altri IDE?

In questa situazione dovresti probabilmente chiedere all'utente, in fase di progettazione, di fornire o cercare un percorso aggiungendo una proprietà sul tuo oggetto per la modifica. Il codice temporale di progettazione può quindi utilizzare il valore della proprietà per trovare ciò di cui ha bisogno.

Se stai lavorando a lungo su designer WPF che utilizzano adorner ecc., utilizza " Contesto " Proprietà / tipo

Dettagli: - In fase di progettazione hai istanza di modelItem (presumo che tu lo sappia) in caso contrario, puoi istanziarlo in Sostituisci implementazione del metodo Activate

// nella classe DesignAdorner

public class DesignAdorner : PrimarySelectionAdornerProvider
{
      protected override void Activate(ModelItem item)
        {
                modelItem = item;
        }
}

Ora puoi accedere al percorso corrente dell'applicazione usando il seguente codice a linea singola

string aplicationPathDir = System.IO.Directory.GetParent(modelItem.Context.ToString()).FullName;

Fammi sapere, se non ti aiuta.

Ok, dato l'ulteriore chiarimento qui è quello che vorrei fare.

rimanere in linea con la preoccupazione sollevata da GraemeF, fare ciò che vuoi è fragile e incline a rompere al meglio.

Per questo motivo la pratica generale è di considerare il supporto dei dati in fase di progettazione come un approccio completamente diverso rispetto al supporto dei dati di runtime. Molto semplicemente, l'accoppiamento che stai creando tra il tuo ambiente in fase di progettazione e questo DB è una cattiva idea.

Per fornire semplicemente i dati in fase di progettazione per la visualizzazione, preferisco utilizzare una classe simulata che aderisce a un'interfaccia comune come classe di runtime. Questo mi dà un modo per mostrare i dati che posso garantire siano del tipo giusto e conformi allo stesso contratto del mio oggetto runtime. Tuttavia, questa è una classe completamente diversa che viene utilizzata per il supporto in fase di progettazione (e spesso utilizzata per i test unitari).

Quindi, per esempio. Se avessi una classe di runtime che deve mostrare i dettagli della persona come nome, cognome ed e-mail:

public class Person()
{
    public String FirstName { get; set;}
    public String LastName {get; set;}
    public Email EmailAddress {get; set;}
}

e stavo popolando questo oggetto da un DB in fase di runtime, ma ho anche bisogno di fornire una visualizzazione in fase di progettazione. Introdurrei un'interfaccia IPerson che definisce il contratto a cui aderire, in particolare impone l'esistenza dei getter di proprietà:

public interface IPerson()
{
    String FirstName { get; }
    String LastName { get; }
    Email EmailAddress { get; }
}

Quindi aggiornerei la mia classe Person di runtime per implementare l'interfaccia:

public class Person() : IPerson
{
public String FirstName { get; set;}
public String LastName {get; set;}
public Email EmailAddress {get; set;}
}

Quindi creerei una classe finta che implementa la stessa interfaccia e fornisce valori sensibili per l'utilizzo in fase di progettazione

public MockPerson() : IPerson
{
public String FirstName { get { return "John"; } }
public String LastName { get { return "Smith"; } } 
public Email EmailAddress { get { return new Email("John@smith.com"); } }
}

Quindi implementerei un meccanismo per fornire l'oggetto MockPerson in fase di progettazione e l'oggetto Person reale in fase di esecuzione. Qualcosa come this oppure this . Ciò fornisce il supporto dei dati in fase di progettazione senza la forte dipendenza tra il runtime e gli ambienti in fase di progettazione.

Questo modello è molto più flessibile e ti consentirà di fornire un supporto coerente dei dati in fase di progettazione in tutta la tua applicazione.

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