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.
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.
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.
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.
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.
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.
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.
Esecuzione del cast di Current alla sottoclasse personalizzata di Application.
Esecuzione del cast di MainWindow sulla sottoclasse personalizzata di Window.
Utilizzo del metodo FindResource o del metodo FindName su Current o MainWindow.
Mancato controllo dell'eventuale restituzione di un valore null da parte degli oggetti Application.Current o Application.MainWindow. Se l'oggetto Visual Studio non crea un oggetto applicazione, l'oggetto Application.Current può restituire null.
Mancato controllo dell'eventuale restituzione di un valore null da parte dell'oggetto Assembly.GetEntryAssembly. Per Visual Studio, questo metodo restituisce null.
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.
Per caricare un controllo personalizzato in WPF Designer, è necessario fornire metodi get e set di CLR per tutte le proprietà di dipendenza che sono state definite. Per ulteriori informazioni, vedere Custom Dependency Properties.
Gli strumenti decorativi di tipo ComboBox non sono supportati.
Per utilizzare un controllo Windows Form di terze parti, creare un tipo di UserControl che disponga di un'istanza del controllo del fornitore nell'insieme di Controls. Per ulteriori informazioni, vedere Procedura dettagliata: hosting di un controllo Windows Form di terze parti in un'applicazione WPF.
La fase di progettazione per FlowDocument non è supportata direttamente. Se si desidera utilizzare WPF Designer in un FlowDocumentincorporato, posizionare innanzitutto FlowDocument in un controllo Frame, che è quindi possibile utilizzare in 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