XAML 清除项并将其添加到ObservableCollection时,不执行DataTemplateSelector

vdgimpew  于 2023-01-18  发布在  其他
关注(0)|答案(1)|浏览(130)

在我的. Net Maui应用程序中,我想使用DataTemplateSelector显示存储在ObservableCollection中的数据。因此,我使用Microsoft文档创建了一个示例。https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/datatemplate?view=net-maui-7.0
我在视图模型中有一个ObservableCollection<DataBaseItem> DataBaseItemsFiltered;。在视图中,我得到了一个集合视图来使用DataTemplateSelector显示数据。

<CollectionView ItemsSource="{Binding DataBaseItemsFiltered}"
                        ItemTemplate="{StaticResource DBISelector}">

在我更新ObservableCollection之前,一切都按预期运行。这是启动应用程序后的样子。"BestCompany"拥有的每一项都突出显示(如预期)。

但如果我更新/过滤"ObservableCollection"(出于测试目的,仅清除并添加原始项)

[RelayCommand]
void Filter()
{
    ...
    DataBaseItemsFiltered.Clear();
    foreach (DataBaseItem item in dataBaseItems)
    {
        DataBaseItemsFiltered.Add(item);
    }                
}

这种事常有。

每次调用Filter()函数时,这种行为都会发生变化。我发现,只有在启动时,才会为集合中的每个项目调用自定义DataTemplateSelector。然后,就再也不会调用它了。但是,如果我更改Filter()函数以示例化new ObservableCollection

DataBaseItemsFiltered = new(dataBaseItems);

它工作正常,在调试时,我可以看到每次调用filter函数时都会调用DataTemplateSelector(如预期)。
我的问题:有人知道如何解决这个问题吗?我是否以一种不适合的方式使用ObservableCollection?是否有一种变通方法可以告诉视图必须为集合视图中的每个项目调用DataTemplateSelector?
如果你需要更多的代码,请告诉我。并提前感谢你。
编辑19.12.2022回答ToolMakerSteve的问题。
1.是,DataBaseItemsFiltered是公共属性(由MVVMToolkit生成)

[ObservableProperty]
ObservableCollection<DataBaseItem> dataBaseItemsFiltered;

1.是的。刚测试过
1.筛选函数绑定到搜索栏的SearchCommand

<SearchBar Grid.Column="1" 
                           SearchCommand="{Binding FilterCommand}" 
                           Text="{Binding CompanyFilterText}"/>

编辑2 19.12.2022回答沈利群-微软提问。
显然ObservableCollection(OC)的行为是这样的:
1.如果添加了项并且计数大于OC示例化后的计数,则将触发DataTemplateSelector。
示例:从中删除1个项目,然后向OC添加2次,将删除项目的模板分配给正在添加的第一个项目(不触发DataTemplateSelector)。对于第二个项目,将触发DataTemplateSelector(正在分配正确的模板)
1.删除n个项目和添加n个项目将分配模板LIFO类似。
示例:使用DataTemplate1删除一项。使用DataTemplate2删除另一项。添加新项=〉正在分配DataTemplate2(无论如何)。添加新项=〉正在分配DataTemplate1(无论如何)。

q43xntqr

q43xntqr1#

我找到了一个解决这个问题的方法。顺便说一句:Android上不会出现这个问题,无法检查iOS和MAC。
因此,问题似乎出在DataTemplateSelector中使用的DataTemplate(或者更准确地说是其子)上。

工作版本

如果子节点继承自LayoutGridVerticalStackLayout等),则一切都将按预期工作,无论如何,当向ObservableCollection添加项时,DataTemplateSelector都会被触发。
示例:(使用Grid作为DataTemplate的子元素)

<DataTemplate x:Key="DataTemplateDefault_Good">
    <Grid>
        <Frame>
            <HorizontalStackLayout x:DataType="local:SomeItem"
                                    Spacing="30">
                <Label Text="{Binding Id}" />
                <Label Text="{Binding Name}" />
            </HorizontalStackLayout>
        </Frame>
    </Grid>
</DataTemplate>

版本不工作

否则(DataTemplate的子级继承自ViewContentView)将显示我在问题中描述的行为。DataTemplateSelector仅在将项目添加到ObservableCollection并且ObservableCollection的大小大于示例化后的大小时触发。
示例:(使用Frame作为DataTemplate的子元素)

<DataTemplate x:Key="DataTemplateDefault_Bad">
    <Frame>
        <HorizontalStackLayout x:DataType="local:SomeItem"
                                Spacing="30">
            <Label Text="{Binding Id}" />
            <Label Text="{Binding Name}" />
        </HorizontalStackLayout>
    </Frame>
</DataTemplate>

我希望能对这种行为做出进一步的解释。这可能是一个bug,应该报告吗?

相关问题