Risoluzione dei problemi relativi agli errori di caricamento di WPF e Silverlight Designer

WPF Designer 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. Gli esempi contenuti in questo argomento si concentrano su WPF, ma la maggior parte dei problemi, delle tecniche e delle soluzioni si applicano a WPF e a Silverlight.

Nota

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

Esecuzione del debug di un errore del caricamento

Utilizzare il debugger Visual Studio per accedere al codice in fase di progettazione. È possibile utilizzare una seconda istanza di Visual Studio per eseguire il debug degli errori del caricamento. Per ulteriori informazioni, vedere Procedura: eseguire il debug di un errore di caricamento della finestra di progettazione.

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. 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.

  4. 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.

  5. 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.

  6. 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. Per Silverlight, utilizzare la proprietà IsInDesignTool.

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(MainWindow))
            // 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;
    }
}

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

Concetti

Exception Handling (Debugging)

Altre risorse

Procedura: eseguire il debug di un errore di caricamento della finestra di progettazione

Debug e interpretazione degli errori in Progettazione WPF

Procedure dettagliate relative all'uso di XAML e del codice