Устранение неполадок, связанных с ошибками загрузки конструктора WPF и Silverlight

Конструктор WPF для Visual Studio включает многофункциональный и расширяемый визуальный конструктор для создания XAML-кода. Если XAML-файл не загружается в конструктор, есть несколько вариантов устранения неполадок. В этом разделе приводятся некоторые советы и описываются способы, позволяющие устранить ошибки загрузки сред. Конструктор WPF. Приведенные в этом разделе примеры посвящены WPF, но большинство вопросов, приемов и решений применимо и к WPF, и к Silverlight.

ПримечаниеПримечание

Многие из способов, описанных в этом разделе, также применимы к средству Expression Blend.

Используйте отладчик Visual Studio для перехода в код во время разработки. Для отладки сбоев загрузки можно использовать второй экземпляр Visual Studio. Дополнительные сведения см. в разделе Практическое руководство. Отладка ошибки загрузки конструктора.

Следующие действия помогут устранить ошибки загрузки сред. Конструктор WPF.

  1. Прочитайте все полученные сообщения об исключениях.

    Это может казаться очевидным, но в случае получения исключения следует внимательно прочитать сообщение. В некоторых случаях это помогает быстро найти причину проблемы. Дополнительные сведения см. в разделе Отладка и интерпретация ошибок в конструкторе WPF.

  2. Определите, не обусловлена ли проблема конкретной реализацией.

    Создайте и запустите приложение, чтобы определить является ли неполадка результатом только реализации или взаимодействия с сред. Конструктор WPF. Если приложение строится и запускается, ошибка времени разработки скорее всего вызвана реализацией.

  3. Определите, является ли проблемой ошибка загрузки.

    Если конструктору не удается выполнить загрузку из-за возникновения исключения, проблемой, скорее всего, является ошибка загрузки. Если имеется пользовательский код, который загружается во время разработки, и во время разработки возникают исключения или ошибки загрузки, см. раздел Написание кода для времени разработки ниже.

  4. Просмотрите код, который загружается во время разработки.

    Существует два подхода к записи кода, который также выполняется во время разработки. Первый подход заключается в написании защитного кода путем проверки входных параметров для классов. Второй подход заключается в проверке активности режима разработки вызовом метода GetIsInDesignMode. Дополнительные сведения см. в разделе Написание кода для времени разработки ниже.

  5. Просмотрите другие области кода.

    Некоторые советы по программированию при работе с сред. Конструктор WPF см. в разделе Советы про программированию ниже.Методы написания наиболее надежного кода см. в разделе Рекомендации по программированию ниже.

  6. Если проблемы остаются, можно перейти на форум разработчиков WPF на MSDN (на английском языке), чтобы связаться с другими разработчиками, использующими сред. Конструктор WPF. Для отправки отчета о вероятных проблемах и возможных предложений воспользуйтесь веб-узлом Visual Studio и .NET Framework. Feedback (на английском языке).

Убедитесь, что код выполняется как во время разработки, так и во время выполнения. Если код выполняется во время разработки, не следует полагать, что Application.Current является разрабатываемым приложением. Например, при использовании средства Expression Blend Current является Expression Blend. MainWindow is not your application's main window." data-guid="fccc271404d7a420a4101bb6bc3782d3">Во время разработки MainWindow не является главным окном разрабатываемого приложения. К типичным операциям, вызывающим сбой настраиваемого элемента управления во время разработки, относятся:

  • приведение типа Current к настраиваемым подклассам Application,

  • Приведение типа MainWindow к пользовательскому подклассу Window.

  • использование метода FindResource или FindName на Current или MainWindow,

  • отсутствие проверки возвращения методом Application.Current или Application.MainWindow значения null. Если Visual Studio не создает объект приложения, то Application.Current может возвращать значение null,

  • отсутствие проверки возвращения методом Assembly.GetEntryAssembly значения null. Для среды Visual Studio этот метод возвращает значениеnull.

Существует два подхода к написанию кода для времени разработки. Первый подход заключается в написании защитного кода путем проверки входных параметров классов, таких как преобразователи значений. Второй подход заключается в проверке активности режима разработки вызовом метода GetIsInDesignMode. Для Silverlight используйте свойство IsInDesignTool.

Проверка входных параметров необходима для некоторых реализаций, так как для некоторых входных данных среда разработки предоставляет типы, отличающиеся от тех, что предоставляет среда выполнения.

Обычно, для селекторов стиля и преобразователей значений требуется один из этих подходов для правильной работы во время разработки.

Преобразователи значений

В пользовательской реализации IValueConverter должна проводиться проверка на наличие значения null и на ожидаемый тип первого параметра методаConvert. В следующем 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.

  • Если требуется загрузить пользовательский элемент управления в сред. Конструктор WPF, необходимо указать методы получения и установки среды CLR для всех определяемых свойств зависимостей. Дополнительные сведения см. в разделе Пользовательские свойства зависимостей.

  • Графические элементы типа ComboBox не поддерживаются.

  • Чтобы использовать сторонний элемент управления Windows Forms, создайте тип UserControl, у которого есть экземпляр элемента управления от стороннего производителя в своей коллекции Controls. Дополнительные сведения см. в разделе Пошаговое руководство. Размещение стороннего элемента управления Windows Forms в приложении WPF.

  • Время разработки для FlowDocument непосредственно не поддерживается. Если требуется использовать сред. Конструктор WPF для встроенного FlowDocument, сначала поместите FlowDocument в элемент управления Frame, который затем можно использовать в сред. Конструктор WPF.

Ниже приведены некоторые рекомендации по программированию, позволяющие создавать более надежный код для сред. Конструктор WPF.

  • Всегда заключайте области изменения в операторы using или блоки try/finally. Если возникает исключение, изменение прерывается в вызове Dispose. Дополнительные сведения см. в разделе ModelEditingScope.

  • Для перемещения элемента управления из одного контейнера в другой используйте метод ModelEditingScope. Если этого не сделать, то возникнет исключение.

  • В WPF и сред. Конструктор WPF не задавайте значение свойства по умолчанию, если планируется его очистка. Для значений NaN таких, как Heightследует вызвать метод ClearValue вместо присваивания NaN.

  • При извлечении значений из свойства, используйте вычисляемое значение свойства. Это означает, что следует использовать свойство ComputedValue вместо метода GetCurrentValue модели ModelItem. Метод GetCurrentValue возвращает привязки и другие выражения, если они были сохранены в XAML-файле, поэтому в некоторых случаях могут возникать исключения при приведении типов.


Страница сайта http://www.interface.ru
Оригинал находится по адресу http://www.interface.ru/home.asp?artId=29626