Condividi tramite


Risoluzione dei problemi relativi agli errori di caricamento di Progettazione WPF

Aggiornamento: novembre 2007

Progettazione Windows Presentation Foundation (WPF) per Visual Studio include una finestra di progettazione visiva sofisticata ed estensibile che raffigura il codice XAML. Se il file XMAL non viene caricato nella finestra di progettazione, è possibile eseguire diverse operazioni per cercare di identificare il problema. In questo argomento vengono descritti alcuni suggerimenti e tecniche per la risoluzione di problemi relativi ad errori di caricamento di WPF Designer.

Nota:

Molte delle tecniche descritte in questo argomento possono essere applicate anche a Expression Blend.

Passaggi per la risoluzione dei problemi

I passaggi seguenti consentono di risolvere i problemi relativi ad errori di caricamento di WPF Designer.

  1. Leggere tutti i messaggi di eccezione che vengono ricevuti.

    Potrebbe sembrare ovvio, ma se si ottiene un'eccezione, occorre leggerne il messaggio. In alcuni casi, il messaggio aiuta a diagnosticare rapidamente il problema. Per ulteriori informazioni, vedere Debug e interpretazione degli errori in Progettazione WPF.

  2. Determinare se il problema è nell'implementazione.

    Compilare ed eseguire l'applicazione per determinare se il problema è il risultato solo dell'implementazione o di un'interazione con WPF Designer. Se si riesce a compilare ed eseguire l'applicazione, è probabile che la causa dell'errore in fase di progettazione sia l'implementazione.

  3. Utilizzare il debugger Visual Studio per accedere al codice in fase di progettazione. Per ulteriori informazioni, vedere Procedura dettagliata: debug di controlli personalizzati WPF in fase di progettazione.

  4. Determinare se il problema è un errore di caricamento.

    Se la visualizzazione Progettazione non viene caricata a causa di un'eccezione, è probabile che il problema sia un errore di caricamento. Se in fase di progettazione viene caricato del codice personalizzato e in questa fase si verificano eccezioni o errori di caricamento, vedere la sezione Scrittura di codice per la fase di progettazione in questo argomento. Se si sta lavorando con delle risorse e queste non vengono caricate, vedere la sezione Risorse di controlli utente e controlli personalizzati in fase di progettazione in questo argomento.

  5. Rivedere il codice caricato in fase di progettazione.

    Esistono due approcci alla scrittura di codice eseguibile anche in fase di progettazione. Il primo approccio consiste nello scrivere codice difensivo controllando i parametri di input alle classi. Il secondo approccio consiste nel controllare se la modalità di progettazione è attiva chiamando il metodo GetIsInDesignMode. Per ulteriori informazioni, vedere la sezione Scrittura di codice per la fase di progettazione in questo argomento.

  6. Rivedere le altre aree del codice.

    Rivedere la sezione Suggerimenti per la programmazione in questo argomento per ottenere alcuni suggerimenti per la programmazione quando si utilizza WPF Designer. Rivedere la sezione Tecniche di programmazione più idonee di questo argomento per le tecniche di scrittura di codice più affidabile.

  7. Se vengono ancora riscontati dei problemi, è possibile visitare il WPF Designer forum on MSDN (informazioni in lingua inglese) per comunicare con altri sviluppatori che utilizzano WPF Designer. Per riportare potenziali problemi o fornire suggerimenti, utilizzare il sito Visual Studio and .NET Framework Feedback (informazioni in lingua inglese).

Scrittura di codice per la fase di progettazione

Assicurarsi che il codice venga eseguito correttamente in fase di progettazione così come in fase di esecuzione. Se il codice viene eseguito correttamente in fase di progettazione, non presupporre che Application.Current sia l'applicazione. Ad esempio, se si sta utilizzando Expression Blend, Current è Expression Blend. In fase di progettazione, MainWindow non è la finestra principale dell'applicazione. Le tipiche operazioni che determinano l'errata esecuzione di un controllo personalizzato in fase di progettazione includono gli elementi seguenti.

Esistono due approcci alla scrittura di codice per la fase di progettazione. Il primo approccio consiste nello scrivere codice difensivo controllando i parametri di input alle classi, quali i convertitori di valori. Il secondo approccio consiste nel controllare se la modalità di progettazione è attiva chiamando il metodo GetIsInDesignMode.

La verifica dei parametri di input per alcune implementazioni è necessaria perché l'ambiente di progettazione fornisce per alcuni input tipi differenti da quelli forniti dall'ambiente di runtime.

I selettori di stili e i convertitori di valori richiedono in genere l'uso di uno di questi approcci per essere eseguiti in modo corretto in fase di progettazione.

Convertitori di valori

Le implementazioni di IValueConverter personalizzate devono controllare il valore null e il tipo previsto nel primo parametro del metodo Convert. Nel seguente esempio di codice XAML viene mostrata un'associazione a Application.Current che non viene eseguita correttamente in fase di progettazione se il convertitore di valori non è implementato correttamente.

<ComboBox.IsEnabled>
    <MultiBinding Converter="{StaticResource specialFeaturesConverter}">
        <Binding Path="CurrentUser.Rating" Source="{x:Static Application.Current}"/>
        <Binding Path="CurrentUser.MemberSince" Source="{x:Static Application.Current}"/>
    </MultiBinding>
</ComboBox.IsEnabled>

L'associazione genera un'eccezione in fase di progettazione perché Application.Current si riferisce all'applicazione della finestra di progettazione anziché all'applicazione. Per impedire l'eccezione, il convertitore di valori deve controllare i parametri di input o verificare la modalità di progettazione.

Nell'esempio di codice seguente viene illustrato come controllare i parametri di input in un convertitore di valori che restituisce true se due parametri di input soddisfano la particolare regola business.

public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    // Check the values array for correct parameters.
    // Designers may send null or unexpected values.
    if (values == null || values.Length < 2) return false;
    if (!(values[0] is int)) return false;
    if (!(values[1] is DateTime)) return false;

    int rating = (int)values[0];
    DateTime date = (DateTime)values[1];

    // If the user has a good rating (10+) and has been a member for 
    // more than a year, special features are available.
    if((rating >= 10) && 
        (date.Date < (DateTime.Now.Date - new TimeSpan(365, 0, 0, 0))))
    {
        return true;
    }
    return false;
}

Il secondo approccio alla scrittura di codice per la fase di progettazione consiste nel controllare se la modalità di progettazione è attiva. Nell'esempio di codice seguente viene mostrato un controllo della modalità di progettazione al posto del controllo del parametro mostrato prima.

public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    // Check for design mode. 
    if ((bool)(DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue)) 
    {
        return false;
    }

    int rating = (int)values[0];
    DateTime date = (DateTime)values[1];

    // If the user has a good rating (10+) and has been a member for 
    // more than a year, special features are available.
    if((rating >= 10) && 
        (date.Date < (DateTime.Now.Date - new TimeSpan(365, 0, 0, 0))))
    {
        return true;
    }
    return false;
}

Selettori di stile

Anche i selettori di stile personalizzati devono essere implementati per funzionare in modalità di progettazione. Nel seguente esempio di codice XAML viene mostrato un selettore di modello personalizzato che utilizza Application.MainWindow in fase di esecuzione per determinare quale risorsa viene restituita come DataTemplate. In fase di progettazione questa risorsa potrebbe non essere disponibile, pertanto l'override di SelectTemplate in questa fase restituisce null.

<local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>
<ListBox Width="400" Margin="10"
    ItemsSource="{Binding Source={StaticResource myTodoList}}"
    ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
    HorizontalContentAlignment="Stretch" 
    IsSynchronizedWithCurrentItem="True"/>

Nell'esempio di codice riportato di seguito viene mostrata l'implementazione del selettore di stile.

public class TaskListDataTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(
        object item, 
        DependencyObject container)
    {
        if (item != null && item is Task)
        {
            Task taskitem = item as Task;
            Window window = Application.Current.MainWindow;

            // To run in design mode, either test for the correct window class
            // or test for design mode.
            if (window.GetType() == typeof(Window1))
            // Or check for design mode: 
            //if (!DesignerProperties.GetIsInDesignMode(window))
            {
                if (taskitem.Priority == 1)
                return window.FindResource("importantTaskTemplate") as DataTemplate;
                else
                return window.FindResource("myTaskTemplate") as DataTemplate;
            }
        }
        return null;
    }
}

Risorse di controlli utente e controlli personalizzati in fase di progettazione

Per impostazione predefinita, le risorse di UserControl e di controlli personalizzati che sono disponibili in fase di esecuzione potrebbero non esserlo in fase di progettazione. Quando si aggiungono controlli personalizzati e controlli utente a una Page o una Window nell'area di progettazione, viene creata un'istanza del controllo. Le risorse in App.xaml non sono disponibili alle istanze di UserControl e di controllo personalizzato caricate in una pagina o una finestra.

Per rendere disponibili le risorse in fase di progettazione, inserirle in un dizionario risorse separato e includerlo in App.xaml e nel codice XAML del controllo. Modificare tutti i riferimenti StaticResource in riferimenti DynamicResource. Nell'esempio di codice seguente viene mostrato come condividere un dizionario risorse in modo che le risorse siano disponibili in fase di progettazione.

UserControl1.xaml

<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Dictionary1.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>

App.xaml

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Dictionary1.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

Sintassi di URI di tipo pack

Non è necessario utilizzare riferimenti di risorsa relativi all'applicazione. Nell'esempio di codice seguente viene mostrata la sintassi basata sull'applicazione che potrebbe generare errori in fase di progettazione.

<Image Name="image1" Source="pack://application:,,,/Image1.bmp" />

Tali riferimenti sono relativi all'applicazione anziché alla DLL. L'utilizzo di un riferimento di risorsa relativo all'applicazione in una DLL rende la DLL dipendente dalle risorse dell'applicazione padre. Questo approccio è fragile e non ne viene garantito il funzionamento in fase di progettazione.

Anziché utilizzare riferimenti di risorsa relativi all'applicazione, aggiungere risorse alla DLL e utilizzare riferimenti di risorsa basati su componenti. Per ulteriori informazioni, vedere URI di tipo pack in Windows Presentation Foundation.

Negli esempi di codice seguenti viene mostrata la sintassi basata su componenti, vale a dire l'approccio consigliato.

<Image Name="image1" Source="/TestHostApp;component/Image1.bmp" />
<Image Name="image1" Source="pack://application:,,,/TestHostApp;component/Image1

Suggerimenti per la programmazione

Di seguito vengono indicati alcuni suggerimenti di programmazione per quando si lavora con WPF Designer.

Tecniche di programmazione più idonee

Di seguito vengono illustrate alcune tecniche di programmazione ritenute più idonee per la scrittura di codice più affidabile per WPF Designer.

  • Eseguire sempre il wrapping degli ambiti di modifica in istruzioni using o blocchi try/finally. Se viene generata un'eccezione, la modifica viene interrotta nella chiamata Dispose. Per ulteriori informazioni, vedere ModelEditingScope.

  • Utilizzare un oggetto ModelEditingScope per spostare un controllo da un contenitore a un altro. Se questa operazione non viene eseguita, verrà generata un'eccezione.

  • In WPF e WPF Designer, non impostare il valore di una proprietà sul valore predefinito se si intende cancellarlo. Per i valori NaN, quali Height, chiamare il metodo ClearValue anziché assegnare NaN.

  • Quando si recuperano valori da una proprietà, utilizzare il valore calcolato della proprietà. Questo significa che occorre utilizzare la proprietà ComputedValue anziché il metodo GetCurrentValue di ModelItem. Il metodo GetCurrentValue restituisce associazioni e altre espressioni se sono memorizzate nel codice XAML, pertanto è possibile in alcuni casi ottenere eccezioni di cast.

Vedere anche

Altre risorse

Debug e interpretazione degli errori in Progettazione WPF

Procedure dettagliate relative all'uso di XAML e del codice

Concetti di base sulla estensibilità

Informazioni sull'estensibilità Progettazione WPF