简体   繁体   English

UWP Treeview C# 中的无效转换异常

[英]Invalid Cast Exception in UWP Treeview C#

When using a treeview that is bound to a three tier hierarchical collection (Order - SKU - Location).使用绑定到三层分层集合(订单 - SKU - 位置)的 treeview 时。 I am using a DataTemplateSelector to choose the TreeViewItem template to use.我正在使用 DataTemplateSelector 来选择要使用的 TreeViewItem 模板。 I am getting an Invalid exception exactly the same as in this post when I scroll - the exception seems to occur faster if I scroll faster.当我滚动时,我得到一个与这篇文章完全相同的无效异常——如果我滚动得更快,异常似乎发生得更快。

I have attempted both suggested solutions in that post (wrapping the treeview in a scroll viewer, and the custom user control).我在那篇文章中尝试了两种建议的解决方案(将 treeview 包装在滚动查看器中,以及自定义用户控件)。 Wrapping the TreeView does not help, and I cannot get the custom user control solution to work correctly for me and I wonder if it is related to the fact I have a three tier collection instead of two tiers.包装 TreeView 没有帮助,我无法让自定义用户控制解决方案为我正常工作,我想知道这是否与我有一个三层集合而不是两层的事实有关。 The code for the custom UserControl is exactly the same as in the linked post except modified for my collection.自定义 UserControl 的代码与链接帖子中的代码完全相同,只是针对我的收藏进行了修改。 When I try it it only binds one tier of the collection to the treeview.当我尝试它时,它只将集合的一层绑定到 treeview。 What I am looking for is a solution prevents the framework code from reusing the templates which appears to be what is causing the exception.我正在寻找的是一种解决方案,可以防止框架代码重用模板,这似乎是导致异常的原因。

Here is my XAML and code for the TreeView that currently produces the exception:这是我的 XAML 和当前产生异常的 TreeView 的代码:

<Page
x:Class="PickSheetManager.Views.PickSheetManagerPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:winui="using:Microsoft.UI.Xaml.Controls"
xmlns:model="using:PickSheetManager.Core.Models"
xmlns:behaviors="using:PickSheetManager.Behaviors"
xmlns:templateSelectors="using:PickSheetManager.TemplateSelectors"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:controls1="using:PickSheetManager.Controls"
xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
xmlns:i="using:Microsoft.Xaml.Interactivity"
Style="{StaticResource PageStyle}"
behaviors:NavigationViewHeaderBehavior.HeaderMode="Never"
mc:Ignorable="d">

<Page.Resources>        
    <DataTemplate x:Key="OrderTemplate" x:DataType="model:Order">
        <winui:TreeViewItem
            AutomationProperties.Name="{x:Bind PoIDx}"
            ItemsSource="{x:Bind SKUs}" IsExpanded="True">
            <StackPanel x:Name="stack" Orientation="Horizontal">
            <i:Interaction.Behaviors>
                <ic:DataTriggerBehavior Binding ="{x:Bind NotEnoughInventory}" Value="True">
                    <ic:ChangePropertyAction TargetObject="{Binding ElementName=stack}" PropertyName="Background" Value="Red" />
                </ic:DataTriggerBehavior>
            </i:Interaction.Behaviors>
            <CheckBox IsChecked="{x:Bind IsSelected, Mode=TwoWay}" Padding="5" MinWidth="0"/>
            <TextBlock Text="PoIDx: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            <TextBlock Text="{x:Bind PoIDx}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            <TextBlock Text="Delivery: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            <TextBlock Text="{x:Bind DeliveryType}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            <TextBlock Text="Delivery: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            <TextBlock Text="{x:Bind DeliveryType}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            <TextBlock Text="Type: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            <TextBlock Text="{x:Bind OrderType}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            <TextBlock Text="Total Quantity: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            <TextBlock Text="{x:Bind TotalQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            <TextBlock Text="Printed: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            <TextBlock Text="{x:Bind IsPrinted}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            <TextBlock Text="Notes: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            <TextBox Text="{x:Bind Notes, Mode=TwoWay}" Margin="{StaticResource XXSmallTopRightBottomMargin}" Width="150"/>
        </StackPanel>
        </winui:TreeViewItem>
    </DataTemplate>        

    <DataTemplate x:Key="SKUTemplate" x:DataType="model:SKU">
        <winui:TreeViewItem
            AutomationProperties.Name="{x:Bind SKUNum}"
            ItemsSource="{x:Bind Locations}" IsExpanded="True">
            <StackPanel x:Name="stack2" Orientation="Horizontal">
                <i:Interaction.Behaviors>
                    <ic:DataTriggerBehavior Binding ="{x:Bind NotEnoughInventory}" Value="True">
                        <ic:ChangePropertyAction TargetObject="{Binding ElementName=stack2}" PropertyName="Background" Value="Yellow" />
                    </ic:DataTriggerBehavior>
                </i:Interaction.Behaviors>
                <CheckBox IsChecked="{x:Bind IsSelected, Mode=TwoWay}" Padding="5" MinWidth="0" />
                <TextBlock Text="SKU: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind SKUNum}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Needed: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind NeedQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Available: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind AvailableQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            </StackPanel>
        </winui:TreeViewItem>
    </DataTemplate>        

    <DataTemplate x:Key="LocationTemplate" x:DataType="model:Location">
        <winui:TreeViewItem
            AutomationProperties.Name="{x:Bind LocationName}"
            IsExpanded="True">
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{x:Bind IsSelected, Mode=TwoWay}" Padding="5" MinWidth="0" />
                <TextBlock Text="{x:Bind LocationName}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Pick Type: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind PickType}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Pick Quantity: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind PickQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Available Quantity: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind AvailableQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBox Text="{x:Bind Notes, Mode=TwoWay}" Margin="{StaticResource XXSmallTopRightBottomMargin}" Width="150" />
            </StackPanel>
        </winui:TreeViewItem>
    </DataTemplate>      


    <templateSelectors:SampleDataTemplateSelector x:Key="TreeViewTemplateSelector"
        OrderDetailTemplate="{StaticResource OrderTemplate}"
        SKUDetailTemplate="{StaticResource SKUTemplate}"
        LocationDetailTemplate="{StaticResource LocationTemplate}" />
</Page.Resources>

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="treeViewColumn" Width="6*" />
        <ColumnDefinition x:Name="detailViewColumn" Width="4*" />
    </Grid.ColumnDefinitions>
    <Grid Grid.Column="0">
        <Grid.RowDefinitions>
            <RowDefinition x:Name="treeViewRow" Height="8*" />
            <RowDefinition x:Name="controlRow" Height="2*" />
        </Grid.RowDefinitions>
        <ScrollViewer x:Name="WrapViewer" Grid.Row="0" Grid.Column="0" Padding="{StaticResource DetailPageMargin}">
        </ScrollViewer>
        <winui:TreeView
            x:Name="treeView"
            Grid.Row="0"
            SelectionMode="Single"
            ItemsSource="{x:Bind ViewModel.openOrders}"
            ItemTemplateSelector="{StaticResource TreeViewTemplateSelector}">
            <i:Interaction.Behaviors>
                <behaviors:TreeViewCollapseBehavior x:Name="collapseBehavior" />
                <ic:EventTriggerBehavior EventName="ItemInvoked">
                    <ic:InvokeCommandAction Command="{x:Bind ViewModel.ItemInvokedCommand}" />
                </ic:EventTriggerBehavior>
            </i:Interaction.Behaviors>
        </winui:TreeView>
    </Grid>
    <Grid Grid.Column="1">
        <Grid.RowDefinitions>
            <RowDefinition x:Name="detailViewRow" Height="4*" />
            <RowDefinition x:Name="iarRow" Height="4*" />
            <RowDefinition x:Name="controlRow2" Height="2*" />
        </Grid.RowDefinitions>
    </Grid>
</Grid>    

The collection being bound被绑定的集合

 public ObservableCollection<Order> openOrders { get; } = new ObservableCollection<Order>();


 public async Task LoadDataAsync()
 {           
     var data2 = await OrderDataLoader.GetTreeViewDataAsync();
     foreach (var item in data2)
     {
         openOrders.Add(item);
     }                   
 }

And the DataTemplateSelector code:和 DataTemplateSelector 代码:

public class SampleDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate OrderDetailTemplate { get; set; }

    public DataTemplate SKUDetailTemplate { get; set; }

    public DataTemplate LocationDetailTemplate { get; set; }

    protected override DataTemplate SelectTemplateCore(object item)
    {
        return GetTemplate(item) ?? base.SelectTemplateCore(item);
    }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        return GetTemplate(item) ?? base.SelectTemplateCore(item, container);
    }

    private DataTemplate GetTemplate(object item)
    {
        switch (item)
        {
            case Order order:
                return OrderDetailTemplate;
            case SKU sku:
                return SKUDetailTemplate;
            case Location location:
                return LocationDetailTemplate;
        }

        return null;
    }
}

Update更新

I have actually tried two different attempts to get the user control to work.我实际上尝试了两种不同的尝试来使用户控件正常工作。 Both resulted in only one tier being displayed.两者都导致仅显示一层。

Attempt #1 UserControl XAML:尝试 #1 用户控制 XAML:

<UserControl
    x:Class="PickSheetManager.Controls.OrderTreeItemControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:winui="using:Microsoft.UI.Xaml.Controls"
    xmlns:model="using:PickSheetManager.Core.Models"
    xmlns:behaviors="using:PickSheetManager.Behaviors"
    xmlns:templateSelectors="using:PickSheetManager.TemplateSelectors"
    xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
    xmlns:controls1="using:PickSheetManager.Controls"
    xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
    xmlns:i="using:Microsoft.Xaml.Interactivity"
    mc:Ignorable="d">

    <UserControl.Resources>
        <DataTemplate x:Name="OrderTemplate" x:DataType="model:Order">
            <StackPanel x:Name="stack" Orientation="Horizontal">
                <i:Interaction.Behaviors>
                    <ic:DataTriggerBehavior Binding ="{x:Bind NotEnoughInventory}" Value="True">
                        <ic:ChangePropertyAction TargetObject="{Binding ElementName=stack}" PropertyName="Background" Value="Red" />
                    </ic:DataTriggerBehavior>
                </i:Interaction.Behaviors>
                <CheckBox IsChecked="{x:Bind IsSelected, Mode=TwoWay}" Padding="5" MinWidth="0"/>
                <TextBlock Text="PoIDx: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind PoIDx}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Delivery: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind DeliveryType}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Delivery: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind DeliveryType}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Type: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind OrderType}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Total Quantity: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind TotalQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Printed: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind IsPrinted}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Notes: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBox Text="{x:Bind Notes, Mode=TwoWay}" Margin="{StaticResource XXSmallTopRightBottomMargin}" Width="150"/>
            </StackPanel>
        </DataTemplate>
        <DataTemplate x:Name="SKUTemplate" x:DataType="model:SKU">            
            <StackPanel x:Name="stack2" Orientation="Horizontal">
                <i:Interaction.Behaviors>
                    <ic:DataTriggerBehavior Binding ="{x:Bind NotEnoughInventory}" Value="True">
                        <ic:ChangePropertyAction TargetObject="{Binding ElementName=stack2}" PropertyName="Background" Value="Yellow" />
                    </ic:DataTriggerBehavior>
                </i:Interaction.Behaviors>
                <CheckBox IsChecked="{x:Bind IsSelected, Mode=TwoWay}" Padding="5" MinWidth="0" />
                <TextBlock Text="SKU: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind SKUNum}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Needed: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind NeedQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Available: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind AvailableQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
            </StackPanel>            
        </DataTemplate>
        <DataTemplate x:Name="LocationTemplate" x:DataType="model:Location">
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{x:Bind IsSelected, Mode=TwoWay}" Padding="5" MinWidth="0" />
                <TextBlock Text="{x:Bind LocationName}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Pick Type: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind PickType}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Pick Quantity: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind PickQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="Available Quantity: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBlock Text="{x:Bind AvailableQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                <TextBox Text="{x:Bind Notes, Mode=TwoWay}" Margin="{StaticResource XXSmallTopRightBottomMargin}" Width="150" />
            </StackPanel>            
        </DataTemplate>
    </UserControl.Resources>

    <Grid>
        <ContentControl x:Name="MainContent"/>
    </Grid>
</UserControl>

Attempt #1.cs尝试#1.cs

    namespace PickSheetManager.Controls
{
    public sealed partial class OrderTreeItemControl : UserControl
    {
        public OrderTreeItemControl()
        {
            this.InitializeComponent();
        }

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

        public static readonly DependencyProperty DataProperty =
            DependencyProperty.Register("Data", typeof(OpenOrdersBase), typeof(OrderTreeItemControl), new PropertyMetadata(null, new PropertyChangedCallback(Data_Changed)));

        private static void Data_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue != null)
            {
                var instance = d as OrderTreeItemControl;
                if (e.NewValue is Location)
                {
                    instance.MainContent.ContentTemplate = instance.LocationTemplate;
                }
                else if (e.NewValue is SKU)
                {
                    instance.MainContent.ContentTemplate = instance.SKUTemplate;
                }
                else
                {
                    instance.MainContent.ContentTemplate = instance.OrderTemplate;
                }
            }
        }
    }
}

Attempt #1 Model Classes尝试 #1 Model 类

public class OpenOrdersBase
{
    public ObservableCollection<Order> Orders { get; } = new ObservableCollection<Order>();
}
public class Order : OpenOrdersBase
{
    public bool IsSelected { get; set; }
    public string OrderNumber { get; set; }
    public string PoIDx { get; set; }
   ...
    public ICollection<SKU> SKUs { get; set; }

}
public class SKU : OpenOrderBase
{
    public bool IsSelected { get; set; }
    public string SKUNum { get; set; }
    ...
    public ICollection<Location> Locations { get; set; }
}
public class Location : OpenOrdersBase
{
    public bool IsSelected { get; set; }
    ...
    public string Notes { get; set; }
}

Attempt #1 Page XAML尝试 #1 页面 XAML

<DataTemplate x:Key="BaseTemplate" x:DataType="model:Order">
            <winui:TreeViewItem
                IsExpanded="False"
                ItemsSource="{x:Bind SKUs}">
                <controls1:TestControl Data="{Binding}"/>
             </winui:TreeViewItem>                        
         </DataTemplate>
...
<winui:TreeView
            x:Name="treeView"
            Grid.Row="0"
            SelectionMode="Single"
            Margin="10,10,10,10"
            ItemsSource="{x:Bind ViewModel.openOrders}"
            ItemTemplate="{StaticResource BaseTemplate}">
            <i:Interaction.Behaviors>
                <behaviors:TreeViewCollapseBehavior x:Name="collapseBehavior" />
                <ic:EventTriggerBehavior EventName="ItemInvoked">
                    <ic:InvokeCommandAction Command="{x:Bind ViewModel.ItemInvokedCommand}" />
                </ic:EventTriggerBehavior>
            </i:Interaction.Behaviors>
        </winui:TreeView>

Attempt #2 The big difference was in the UserControl XAML and In the Models UserControl XAML尝试 #2 最大的区别在于 UserControl XAML 和 Models UserControl XAML

    <UserControl
    x:Class="PickSheetManager.Controls.OrderTreeItemControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:winui="using:Microsoft.UI.Xaml.Controls"
    xmlns:model="using:PickSheetManager.Core.Models"
    xmlns:behaviors="using:PickSheetManager.Behaviors"
    xmlns:templateSelectors="using:PickSheetManager.TemplateSelectors"
    xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
    xmlns:controls1="using:PickSheetManager.Controls"
    xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
    xmlns:i="using:Microsoft.Xaml.Interactivity"
    mc:Ignorable="d">

    <UserControl.Resources>

        <DataTemplate x:Name="OrderTemplate" x:DataType="model:Order">
            <winui:TreeViewItem
                AutomationProperties.Name="{x:Bind PoIDx}"
                ItemsSource="{x:Bind SKUs}"
                IsExpanded="True">
                <StackPanel x:Name="stack" Orientation="Horizontal">
                    <i:Interaction.Behaviors>
                        <ic:DataTriggerBehavior Binding ="{x:Bind NotEnoughInventory}" Value="True">
                            <ic:ChangePropertyAction TargetObject="{Binding ElementName=stack}" PropertyName="Background" Value="Red" />
                        </ic:DataTriggerBehavior>
                    </i:Interaction.Behaviors>
                    <CheckBox IsChecked="{x:Bind IsSelected, Mode=TwoWay}" Padding="5" MinWidth="0"/>
                    <TextBlock Text="PoIDx: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="{x:Bind PoIDx}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="Delivery: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="{x:Bind DeliveryType}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="Delivery: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="{x:Bind DeliveryType}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="Type: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="{x:Bind OrderType}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="Total Quantity: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="{x:Bind TotalQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="Printed: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="{x:Bind IsPrinted}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="Notes: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBox Text="{x:Bind Notes, Mode=TwoWay}" Margin="{StaticResource XXSmallTopRightBottomMargin}" Width="150"/>
                </StackPanel>
            </winui:TreeViewItem>

        </DataTemplate>
        <DataTemplate x:Name="SKUTemplate" x:DataType="model:SKU">
            <winui:TreeViewItem
                AutomationProperties.Name="{x:Bind SKUNum}"
                ItemsSource="{x:Bind Locations}"
                IsExpanded="True">
                <StackPanel x:Name="stack2" Orientation="Horizontal">
                    <i:Interaction.Behaviors>
                        <ic:DataTriggerBehavior Binding ="{x:Bind NotEnoughInventory}" Value="True">
                            <ic:ChangePropertyAction TargetObject="{Binding ElementName=stack2}" PropertyName="Background" Value="Yellow" />
                        </ic:DataTriggerBehavior>
                    </i:Interaction.Behaviors>
                    <CheckBox IsChecked="{x:Bind IsSelected, Mode=TwoWay}" Padding="5" MinWidth="0" />
                    <TextBlock Text="SKU: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="{x:Bind SKUNum}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="Needed: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="{x:Bind NeedQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="Available: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="{x:Bind AvailableQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                </StackPanel>
            </winui:TreeViewItem>
        </DataTemplate>
        <DataTemplate x:Name="LocationTemplate" x:DataType="model:Location">
            <winui:TreeViewItem
                AutomationProperties.Name="{x:Bind LocationName}"                
                IsExpanded="True">
                <StackPanel Orientation="Horizontal">
                    <CheckBox IsChecked="{x:Bind IsSelected, Mode=TwoWay}" Padding="5" MinWidth="0" />
                    <TextBlock Text="{x:Bind LocationName}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="Pick Type: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="{x:Bind PickType}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="Pick Quantity: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="{x:Bind PickQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="Available Quantity: " Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBlock Text="{x:Bind AvailableQuantity}" Margin="{StaticResource XXSmallTopRightBottomMargin}" />
                    <TextBox Text="{x:Bind Notes, Mode=TwoWay}" Margin="{StaticResource XXSmallTopRightBottomMargin}" Width="150" />
                </StackPanel>
            </winui:TreeViewItem>
        </DataTemplate>
    </UserControl.Resources>

    <Grid>
        <ContentControl x:Name="MainContent"/>
    </Grid>
</UserControl>

In the code for the user control I simply updated OpenOrdersBase to Order as I removed the inheritance from all the models.在用户控件的代码中,我只是将 OpenOrdersBase 更新为 Order,因为我从所有模型中删除了 inheritance。

Fianlly the Page XAML changed in this manner最后页面 XAML 以这种方式更改

<DataTemplate x:Key="BaseTemplate" x:DataType="model:Order">
    <controls1:TestControl Data="{Binding}"/>                                        
</DataTemplate>

In fact, your attempt 1 is very close to success, and only requires some minor modifications.事实上,您的尝试 1 非常接近成功,只需要进行一些小的修改。

This problem lies in the definition of the class:这个问题在于class的定义:

Order , SKU , Location have a common base class OpenOperBase , which is good, but the base class should provide a common property, rather than a special Order collection. Order , SKU , Location有一个共同的基础 class OpenOperBase ,这很好,但是基础 class 应该提供一个共同的属性,而不是一个特殊的Order集合。

Try this:尝试这个:

public class OpenOrdersBase
{
    public ObservableCollection<OpenOrdersBase> Children { get; set; } = new ObservableCollection<OpenOrdersBase>();
}

In your Order and SKU class, there is a sub-collection attribute, extract them as a separate base class collection attribute, which will see the effect in the data binding later.在你的OrderSKU class 中,有一个子集合属性,将它们提取为单独的基础 class 集合属性,稍后在数据绑定中看到效果。

Now you can delete Order.SKUs and SKU.Locations .现在您可以删除Order.SKUsSKU.Locations

When binding, the content of TestControl does not need to be changed (keep the wording in attempt#1), but the TreeViewItem template needs to change the DataType绑定时TestControl的内容不需要改变(保持尝试#1的写法),但是TreeViewItem模板需要改变DataType

<DataTemplate x:DataType="models:OpenOrdersBase" x:Key="BaseTemplate">
    <TreeViewItem ItemsSource="{x:Bind Children}">
        <controls:TestControl Data="{Binding}"/>
    </TreeViewItem>
</DataTemplate>

Our general idea is as follows:我们的总体思路如下:

  1. Since TreeViewItem only has effect directly as a child of TreeView.Children , the method of attempt #2 is not desirable.由于TreeViewItem仅作为TreeView.Children的子级直接有效,因此尝试 #2 的方法不可取。
  2. The TreeView.ItemTemplate property affects all internal children, so when binding TreeViewItem.ItemsSource , it is best to bind a base class collection, rather than a specific type of collection (such as SKUs ) TreeView.ItemTemplate属性影响所有内部子项,因此在绑定TreeViewItem.ItemsSource时,最好绑定一个基础 class 集合,而不是特定类型的集合(例如SKUs
  3. If you want to display different templates based on the data type, creating a UserControl and judging the type internally is a feasible way (you have already done it).如果你想根据数据类型显示不同的模板,创建一个UserControl并在内部判断类型是一种可行的方法(你已经做过了)。

Thanks.谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM