Share via


WPF 和 Silverlight 設計工具載入失敗疑難排解

WPF Designer for Visual Studio 包含精細且可延伸的視覺化設計工具以供呈現 XAML。 如果您的 XAML 檔案沒有載入到設計工具中,有幾種方式可以讓您試著去了解是什麼地方出了問題。 本主題將說明一些秘訣和技巧,協助您針對 WPF Designer載入失敗進行疑難排解。 本主題中的範例主要以 WPF 為主,但是大部分的問題、技巧和解決方法都適用於 WPF 和 Silverlight。

注意

本主題提供的許多技巧也同樣適用於 Expression Blend。

偵錯載入失敗

使用 Visual Studio 偵錯工具,在設計階段逐步執行程式碼。 您可以使用 Visual Studio 的第二個執行個體來偵錯載入失敗。 如需詳細資訊,請參閱 HOW TO:偵錯設計工具載入失敗

疑難排解步驟

下列步驟可協助您針對 WPF Designer載入失敗進行疑難排解。

  1. 閱讀所收到的任何例外狀況訊息。

    這似乎是顯而易見的步驟,但是如果您收到例外狀況,請詳讀訊息。 在某些情況下,這可幫助您快速診斷問題。 如需詳細資訊,請參閱WPF 設計工具的錯誤偵錯和解譯

  2. 判斷問題是否出於實作 (Implementation)。

    建置並執行應用程式,判斷問題只是實作導致的,還是出於與 WPF Designer的互動。 如果應用程式能夠建置並執行,則設計階段錯誤可能是實作造成的。

  3. 判斷問題是否為載入錯誤。

    如果 [設計] 檢視因例外狀況而無法載入,問題可能就是載入錯誤。 如果您有自訂程式碼在設計階段載入,而在設計階段發生例外狀況或載入失敗,請參閱本主題的撰寫設計階段的程式碼一節。

  4. 檢視在設計階段載入的程式碼。

    撰寫也能在設計階段執行的程式碼有兩種方式。 第一種方式是藉由檢查類別的輸入參數,來撰寫防衛性程式碼。 第二種方式則是藉由呼叫 GetIsInDesignMode 方法,檢查設計模式是否為作用中。 如需詳細資訊,請參閱本主題的撰寫設計階段的程式碼一節。

  5. 檢視程式碼的其他地方。

    請參閱本主題的程式設計提示一節,以了解使用 WPF Designer的一些程式設計提示。 請參閱本主題的程式設計最佳實務一節,了解如何撰寫更穩固程式碼的技巧。

  6. 如果仍有問題,您可以使用 MSDN 上的 WPF 設計工具論壇,與其他使用 WPF Designer的開發人員交流。 若要報告可能的問題或提供建議,請使用 Visual Studio and .NET Framework 意見網站。

撰寫設計階段的程式碼

確定您的程式碼能在設計階段和執行階段執行。 如果您的程式碼在設計階段執行,請不要假設 Application.Current 是您的應用程式。 例如,當您使用 Expression Blend 時,Current 是 Expression Blend。 在設計階段,MainWindow 不是您應用程式的主視窗。 導致自訂控制項在設計階段失敗的常見作業包括下列幾項。

撰寫設計階段的程式碼有兩種方式。 第一種方式是藉由檢查類別的輸入參數,例如值轉換子,來撰寫防衛性程式碼。 第二種方式則是藉由呼叫 GetIsInDesignMode 方法,檢查設計模式是否為作用中。 針對 Silverlight,請使用 IsInDesignTool 屬性。

檢查某些實作的輸入參數之所以必要,是因為設計環境為某些輸入提供的型別與執行階段環境提供的不同。

樣式選取器和值轉換子通常需要使用上述其中一種方式,才能在設計階段正常執行。

值轉換子

您的自訂 IValueConverter 實作應檢查 Convert 方法的第一個參數是否有 null 和必要的型別。 下列 XAML 顯示 Application.Current 的繫結,如果值轉換子未正確實作,該繫結就會在設計階段失敗。

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

繫結會在設計階段引發例外狀況,因為 Application.Current 參考的是設計工具應用程式,而非您的應用程式。 若要避免這個例外狀況,值轉換子就必須檢查其輸入參數或檢查是否處於設計模式。

下列程式碼範例顯示檢查傳回 true 的值轉換子中的輸入參數,確定兩個輸入參數是否符合特定商務邏輯。

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;
}

第二種撰寫設計階段程式碼的方式是檢查設計模式是否為作用中。 下列程式碼範例顯示設計模式檢查,而非前面顯示的參數檢查。

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;
}

樣式選取器

您的自訂樣式選取器也必須實作,以在設計模式中執行。 下列 XAML 顯示自訂樣板選取器,它在執行階段使用 Application.MainWindow 來判斷哪個資源以 DataTemplate 傳回。 在設計階段,這個資源可能無法使用,因此 SelectTemplate 覆寫會在設計階段傳回 null。

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

下列程式碼示範樣式選取器的實作。

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;
    }
}

程式設計提示

下面是一些使用 WPF Designer的程式設計提示。

程式設計最佳實務

下面是一些程式設計最佳實務,說明如何為 WPF Designer撰寫更穩固的程式碼。

  • 請一律將編輯範圍放在 using 陳述式或 try/finally 區塊內。 如果引發例外狀況,會在 Dispose 呼叫中止變更。 如需詳細資訊,請參閱 ModelEditingScope

  • 使用 ModelEditingScope,將控制項從一個容器移至另一個容器。 未能這麼做會引發例外狀況。

  • 在 WPF 和 WPF Designer中,如果要清除某個屬性值,請不要將它設為預設值。 針對 NaN 值 (例如 Height),請呼叫 ClearValue 方法來代替指派 NaN。

  • 從屬性擷取值時,請使用屬性的計算值。 這表示您應使用 ComputedValue 屬性,而非 ModelItemGetCurrentValue 方法。 GetCurrentValue 方法會傳回繫結和其他以 XAML 儲存的運算式,因此在某些情況下可能會發生轉型例外狀況。

請參閱

工作

HOW TO:偵錯設計工具載入失敗

概念

例外狀況處理 (偵錯)

其他資源

WPF 設計工具的錯誤偵錯和解譯

XAML 和程式碼逐步解說