UWP Treeview с селектором данных генерирует ошибку в App.g.cs при изменении размера окна - PullRequest
0 голосов
/ 02 апреля 2020

Team, это что-то очень странное и я не понимаю, как это отлаживать. У меня есть вид дерева. В древовидном представлении у меня есть 2 типа: Посещение клиента

ВСЕ * root элементы - это клиенты ВСЕ дочерние элементы - это посещения

. Я сделал несколько селекторов, чтобы показать правильные значки для уровня: level 1 loaded

Теперь, когда я открываю листья, ЕСЛИ список не превышает конец дерева, он работает: Open within window size

Но если я открою лист, который ПРЕВЫШАЕТ сторону окна: Child opening beyond window size

Я получаю эту ошибку: Error in App.g.cs

Отправитель: Исключение для приложения: {"Specified cast is not valid."}

Сообщение:

"System.InvalidCastException: Unable to cast object of type 'TitoDoc2020.Models.MTreeViewVisit' to type 'TitoDoc2020.Models.MTreeViewPaz'.\r\n   at TitoDoc2020.Views.TitoDocPage.TitoDocPage_obj107_Bindings.SetDataRoot(Object newDataRoot)\r\n   at TitoDoc2020.Views.TitoDocPage.TitoDocPage_obj107_Bindings.ProcessBindings(Object item, Int32 itemIndex, Int32 phase, Int32& nextPhase)"

НО Я НЕ КАРТОЧКА это! Я действительно не понимаю, где это могло произойти.

Завершить проект здесь видно.

1 Ответ

0 голосов
/ 03 апреля 2020

Согласно описанию сообщения об ошибке, причина этого кроется в преобразовании типа привязки и не имеет никакого отношения к тому, находится ли оно вне окна.

Проверьте данные привязки, чтобы убедиться, что вы неправильно связали MTreeViewVisit с MTreeViewPaz.


Обновление

Исходное Можно предположить, что настройка окна вызвала изменение в видимой области, что, в свою очередь, вызвало некоторые TreeView проблемы с загрузкой записи.

Я заметил, что в проекте вы создадите TitoDocContext, когда дело доходит до загрузки данных, что не рекомендуется.

Вы должны только создать TitoDocContext и передавать ссылку там, где это необходимо, а не использовать оператор using для освобождения контекста. Поскольку частое создание DbContext приведет к огромным затратам ресурсов, это также может быть связано с вашим исключением TreeView при загрузке записи. На самом деле я создал список из 1000 записей, и после избавления от SqlServer он работал хорошо.


Обновление

Я воспроизвел ваш вопрос. С точки зрения актуальной проблемы, это должно быть связано с повторным использованием записей в TreeView. Чтобы уменьшить накладные расходы системных ресурсов, TreeView (включая ListView и GridView) будут повторно использовать ранее обработанные шаблоны. Поскольку вы использовали ItemTemplateSelector, фактический тип данных и повторно используемый шаблон несовместимы, что приводит к ошибке.

Я предлагаю создать UserControl вместо ItemTemplateSelector.

1. Извлеките коллекцию посещений и создайте базовый класс

public class MTreeViewBase
{
    public ObservableCollection<MTreeViewVisit> Visits { get; } = new ObservableCollection<MTreeViewVisit>();
}

public class MTreeViewVisit : MTreeViewBase { }
public class MTreeViewPaz : MTreeViewBase { }

2. Создайте UserControl

TestControl.xaml

<UserControl.Resources>
    <DataTemplate x:Name="PAZTemplate" x:DataType="model:MTreeViewPaz">
        <StackPanel Orientation="Horizontal">
            <FontIcon
                    Margin="{StaticResource XXSmallTopRightBottomMargin}"
                    FontFamily="{StaticResource SymbolThemeFontFamily}"
                    Glyph="&#xE77B;" />
            <TextBlock
                    Margin="{StaticResource XXSmallTopRightBottomMargin}"
                    VerticalAlignment="Center"
                    Text="{x:Bind Name}" />
        </StackPanel>
    </DataTemplate>
    <DataTemplate x:Name="VisitTemplate" x:DataType="model:MTreeViewVisit">
        <StackPanel Orientation="Horizontal">
            <FontIcon
                    Margin="{StaticResource XXSmallTopRightBottomMargin}"
                    FontFamily="{StaticResource SymbolThemeFontFamily}"
                    Foreground="{x:Bind ImageColor}"
                    Glyph="{x:Bind ImageSrc}" />
            <TextBlock
                    Margin="{StaticResource XXSmallTopRightBottomMargin}"
                    VerticalAlignment="Center"
                    Text="{x:Bind VisitDescr}" />
        </StackPanel>
    </DataTemplate>
</UserControl.Resources>
<Grid>
    <ContentControl x:Name="MainContent"/>
</Grid>

3. Создайте зависимые атрибуты для внутреннего преобразования

TestControl.xaml.cs

public MTreeViewBase Data
{
    get { return (MTreeViewBase)GetValue(DataProperty); }
    set { SetValue(DataProperty, value); }
}

// Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
    DependencyProperty.Register("Data", typeof(MTreeViewBase), typeof(TestControl), new PropertyMetadata(null,new PropertyChangedCallback(Data_Changed)));

private static void Data_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if (e.NewValue != null)
    {
        var instance = d as TestControl;
        if(e.NewValue is MTreeViewPaz)
        {
            instance.MainContent.ContentTemplate = instance.PAZTemplate;
        }
        else
        {
            instance.MainContent.ContentTemplate = instance.VisitTemplate;
        }
    }
}

4. Измените TreeView и ItemTemplate

<DataTemplate x:Key="BaseTemplate" x:DataType="model:MTreeViewBase">
    <winui:TreeViewItem
        IsExpanded="False"
        ItemsSource="{x:Bind Visits}">
        <controls1:TestControl Data="{Binding}"/>
    </winui:TreeViewItem>
</DataTemplate>

<winui:TreeView
    ...
    ItemTemplate="{StaticResource BaseTemplate}"
    ... />

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

Спасибо .

...