抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

众所周知,AvaloniaUI的ItemsRepeater是一个用于显示数据集合的控件,能够很方便地从一个ObservableCollection中的数据生成多个子控件。

又众所周知,在AvaloniaUI中,实现自定义控件的最佳实践是使用模板控件(TemplatedControl)。

然而,当你想要在TemplatedControl中使用ItemsRepeater时,你会发现,ItemsRepeater内部DataTemplateDataType并不会正确使用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"><!--引入ObservableCollection中使用的数据类型-->

<Style Selector="controls|ScrollBox">
<Setter Property="Template">
<ControlTemplate>
<ScrollViewer>
<ItemsRepeater ItemsSource="{TemplateBinding ItemsSource}">
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="models:ColoredLine"><!--手动设置DataType-->
<SelectableTextBlock IsEnabled="True" Text="{Binding Line}" Foreground="{Binding LineColor}"/>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</ScrollViewer>
</ControlTemplate>
</Setter>
</Style>
</Styles>

与直接在实例控件中使用ItemsRepeater不同,在TemplatedControl中使用ItemsRepeater时,分析器无法直接确定DataTemplate的类型,需要手动指定DataType

为了应用程序的性能,我个人是一直开着编译时绑定的,不知道不使用编译时绑定的应用有没有这个问题。

评论