AvaloniaUI在TemplatedControl中使用ItemsRepeater
众所周知,AvaloniaUI的ItemsRepeater是一个用于显示数据集合的控件,能够很方便地从一个ObservableCollection中的数据生成多个子控件。
又众所周知,在AvaloniaUI中,实现自定义控件的最佳实践是使用模板控件(TemplatedControl)。
然而,当你想要在TemplatedControl中使用ItemsRepeater时,你会发现,ItemsRepeater内部DataTemplate的DataType并不会正确使用ObservableCollection内部的类。例如,以下这种情况会直接报编译错误:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <Styles xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="using:MyApp.Controls">
<Style Selector="controls|ScrollBox"> <Setter Property="Template"> <ControlTemplate> <ScrollViewer> <ItemsRepeater ItemsSource="{TemplateBinding ItemsSource}"> <ItemsRepeater.ItemTemplate> <DataTemplate> <SelectableTextBlock IsEnabled="True" Text="{Binding Line}" Foreground="{Binding LineColor}"/> </DataTemplate> </ItemsRepeater.ItemTemplate> </ItemsRepeater> </ScrollViewer> </ControlTemplate> </Setter> </Style> </Styles>
|
1 2 3 4 5 6 7 8 9 10
| public class ScrollBox : TemplatedControl { public static readonly StyledProperty<ObservableCollection<ColoredLine>> ItemsSourceProperty = AvaloniaProperty.Register<MyTerminal, ObservableCollection<ColoredLine>>(nameof(ItemsSource)); public ObservableCollection<ColoredLine> ItemsSource { get => GetValue(ItemsSourceProperty); set => SetValue(ItemsSourceProperty, value); } }
|
出现的问题是无法解析某某某类型的数据上下文中的字段或属性 ‘Line’。
如果你尝试将DataTemplate中的Binding改为TemplateBinding,残念,它的DataType会变成整个ScrollBox控件。
正解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <Styles xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="using:MyApp.Controls" xmlns:models="using:MyApp.Models">
<Style Selector="controls|ScrollBox"> <Setter Property="Template"> <ControlTemplate> <ScrollViewer> <ItemsRepeater ItemsSource="{TemplateBinding ItemsSource}"> <ItemsRepeater.ItemTemplate> <DataTemplate DataType="models:ColoredLine"> <SelectableTextBlock IsEnabled="True" Text="{Binding Line}" Foreground="{Binding LineColor}"/> </DataTemplate> </ItemsRepeater.ItemTemplate> </ItemsRepeater> </ScrollViewer> </ControlTemplate> </Setter> </Style> </Styles>
|
与直接在实例控件中使用ItemsRepeater不同,在TemplatedControl中使用ItemsRepeater时,分析器无法直接确定DataTemplate的类型,需要手动指定DataType。
为了应用程序的性能,我个人是一直开着编译时绑定的,不知道不使用编译时绑定的应用有没有这个问题。