Получаването на деца на DataTemplate води до катастрофален отказ (WP 8.1)

Опитвам се да създам приложение за Windows Phone 8.1. Всеки път, когато се опитвам да получа дъщерните елементи на DataTemplate (което е необходимо, защото са вградени в ListView), получавам изключение, което описва подробно

Катастрофална повреда (Изключение от HRESULT: 0x8000FFFF (E_UNEXPECTED))

Направих много проста репродукция тук:

В Visual Studio създайте нов шаблон за празно приложение за Windows Phone. В MainPage.xaml, в манипулатора на събитие OnNavigatedTo, добавете един ред код:

var count = VisualTreeHelper.GetChildrenCount(new DataTemplate());

Когато отстраните грешки в това приложение, то веднага казва, че „В потребителския код е възникнало необработено изключение System.Exception.“

Проверих MSDN, за да се уверя, че този метод не трябва да хвърля никакви изключения.


person James Ko    schedule 14.02.2015    source източник


Отговори (1)


Не успява, защото DataTemplate не е визуален обект и няма визуални деца. (Очевидно VisualTreeHelper.GetChildrenCount всъщност не проверява дали предавате визуално изображение и затова виждате катастрофална повреда вместо нормално изключение).

Обикновено не е необходимо да гледате визуалното дърво за ListView. Обикновено можете да зададете своя ItemsSource на колекция от потребителски клас, който съдържа свойства за всичко, от което се нуждаете.

Ако все още се нуждаете от действителните визуални елементи в ListViewItem - и това е крайна мярка - тогава създавате персонализирано прикачено свойство(-и) и го прикачвате към съответния визуален(и) във вашия DataTemplate. Когато вашето прикачено събитие за промяна на свойство се задейства, подателят на събитието ще бъде съответният визуален елемент, а DataContext на този подател ще бъде стойността на данните на този елемент от списъка.

Ако например имате бутон в ListView и искате щракването върху бутона да задейства действие, тогава бихте направили нещо подобно:

    <ListView.ItemTemplate>
        <DataTemplate>
            <Button MyClickHelper.ClickHandler="{Binding}"/>
        </DataTemplate>
    </ListView.ItemTemplate>

След това във вашия клас MyClickHelper:

private static void OnClickHandlerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var button = (Button)d;
    var data = (MyDataType)e.NewValue;
    button.Click += (btn, args) =>
    {
        // do action here based on data above
    }
}

Това се нарича прикачено поведение - прикачено свойство, което променя поведението на бутона. Това е полезен модел, който поддържа добри граници между различните части на кода и позволява на всеки бутон да има предписано поведение без някакъв главен клас, който трябва да управлява директно всички различни бутони.

person NextInLine    schedule 14.02.2015