【问题标题】:ChoosingItemContainerEvent or ItemTemplateSelector选择ItemContainerEvent 或ItemTemplateSelector
【发布时间】:2016-10-30 00:52:20
【问题描述】:

我有 3 个用于列表视图的数据模板。我应该使用什么来将模板分配给传入的项目 - ItemTemplateSelector 或附加到列表视图的 ChooseItemContainer 事件?

直到现在我一直在使用 ItemTemplateSelector,但是当我快速滚动列表时它会出现异常,可能是因为虚拟化。自动生成的尝试将首先添加的项目类型转换为当前添加的项目的数据类型。你能解释一下这种行为吗?

这是我面临的问题的虚拟版本

public class Person
{
    public PersonType Type;

    public string Name;
}

public enum PersonType
{
    Employee, Student, Manager
}

public class Employee : Person
{
    public string Id;
}

public class Student : Person
{
    public string CollegeName;
}

public class Manager : Person
{
    public string Level;
}

在 MainPage.xaml 中,我有以下 DataTemplates 和 ItemTemplateSelector

    <DataTemplate x:Key="EmployeeTemplate" x:DataType="local:Employee">
        <StackPanel Orientation="Horizontal" Background="Bisque">
            <TextBlock Text="{x:Bind Name}" Margin="10,0"/>
            <TextBlock Text="{x:Bind Id}" Margin="10,0"/>
        </StackPanel>
    </DataTemplate>

    <DataTemplate x:Key="StudentTemplate" x:DataType="local:Student">
        <RelativePanel Background="Aqua">
            <TextBlock x:Name="NameBlock" Text="{x:Bind Name}" Margin="10,0"/>
            <TextBlock RelativePanel.RightOf="NameBlock" Text="{x:Bind CollegeName}" Margin="10,0"/>
        </RelativePanel>
    </DataTemplate>

    <DataTemplate x:Key="ManagerTemplate" x:DataType="local:Manager">
        <Grid Background="BurlyWood">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <TextBlock Text="{x:Bind Name}" Margin="10,0"/>
            <TextBlock Grid.Column="1" Text="{x:Bind Level}" Margin="10,0"/>
        </Grid>
    </DataTemplate>

    <local:ListViewItemTemplateSelector x:Key="ItemTemplateSelector"
                                        EmployeeTemplate="{StaticResource EmployeeTemplate}"
                                        StudentTemplate="{StaticResource StudentTemplate}"
                                        ManagerTemplate="{StaticResource ManagerTemplate}"/>

当我快速滚动列表时,MainPage.g.cs 中出现异常

public void DataContextChangedHandler(global::Windows.UI.Xaml.FrameworkElement sender, global::Windows.UI.Xaml.DataContextChangedEventArgs args)
        {
             global::TestApp.Employee data = args.NewValue as global::TestApp.Employee;
             if (args.NewValue != null && data == null)
             {
                throw new global::System.ArgumentException("Incorrect type passed into template. Based on the x:DataType global::TestApp.Employee was expected.");
             }
             this.SetDataRoot(data);
             this.Update();
        }

这里,args.newValue 包含一个位于列表中间某处的学生项目。

【问题讨论】:

  • 我认为虚拟化不会干扰项目选择器。
  • 也许不是。但是为什么容器中的新项被不同数据类型的旧项占用呢?
  • 这里的问题完全相同:非常简单的项目及其 DataTemplates,以及用于选择它们的 DataTemplateSelector。我也使用编译绑定。还怀疑虚拟化会以某种方式导致崩溃。你找到解决办法了吗?

标签: listview uwp uwp-xaml


【解决方案1】:

此异常不是致命的 - Visual Studio 捕获所有“启用”异常。

如果你想避免它被抛出,当它与虚拟化机制为单元指定的内容不同时,将 ListItemView 的内容设置为 null:

protected override DataTemplate SelectTemplateCore(
    object itemViewModel,
    DependencyObject container)
{    
    var itemView = container as ListViewItem;
    if (itemView != null) {
        var content = itemView.Content;
        if (content != null && content.GetType() != itemViewModel.GetType()) {
            itemView.Content = null;
        }
    }
    ... // return DataTemplate for itemViewModel
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-25
    • 2018-11-04
    • 1970-01-01
    • 1970-01-01
    • 2017-10-15
    • 1970-01-01
    相关资源
    最近更新 更多