【发布时间】:2022-01-24 18:10:52
【问题描述】:
Xamarin.Forms 5.0.0.2012、Visual Studio 2019 for Mac 8.10.16
我遇到了一个问题(在 iOS 和 Android 上,在模拟器和物理设备上),我试图在 XAML 中调用一个转换器来描述我们应用程序中的一个新屏幕。这是标记:
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:internal="clr-namespace:Views.Shared"
x:Class="Views.EditPage">
<ContentPage.Resources>
<internal:PictureNameToImageSourceConverter x:Key="PictureNameToImageSourceConverter" />
</ContentPage.Resources>
...
<CollectionView
x:Name="picturesView"
ItemsLayout="HorizontalList"
HeightRequest="90">
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="False" Padding="5">
<Image
HeightRequest="80"
Source="{Binding Path=., Converter={StaticResource PictureNameToImageSourceConverter}}" />
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
CollectionView.ItemsSource 值在代码中设置为 List
这个转换器经过了很好的测试,可以在应用程序的其他几个地方使用,没有问题。当我将 Image 替换为 <Label Text="{Binding Path=.}"/> 时,文本项会按预期显示,因此它看起来不像是绑定或 Path 语法错误。
标记中是否有我没有看到或没有意识到的东西导致了这种情况?或者任何人都可以建议我没有想到的进一步调试?
更新
从未到达转换器第一行的断点。
EDIT 回应 cmets:
来自 EditPage 代码隐藏:
public partial class EditPage : ContentPage
{
internal List<string> PictureNames;
...
protected override void OnAppearing( )
{
base.OnAppearing();
picturesView.ItemsSource = PictureNames;
}
PictureNames 属性实际上是由从 EditPage 导航到的另一个 Page 设置的:
private void saveSelection_Click(object sender, System.EventArgs args)
{
creator.PictureNames = new List<string>();
foreach (SelectableItem<Picture> item in pictureItems)
{
if (item.IsSelected)
{
creator.PictureNames.Add(item.Item.PictureName);
}
}
Navigation.PopAsync();
}
pictureItems 是一个 List,在该屏幕上充当 ListView.ItemsSource,其中图片被选中或取消选中。
更新
在设置了很多断点之后,我确定picturesView.ItemsSource = PictureNames; 行是崩溃发生的地方。看起来很奇怪,它只在模板显示 Image 而不是 Label 时发生,因为实际上从未调用转换器。
更新
添加延迟的技巧确实让我到达了断点。我发现比以往任何时候都更令人费解:传递给我们转换器的 Convert 方法的 value 参数是 null。这是从图片选择屏幕返回的情况,或者如果我设置绑定列表以响应 Button 而不是 OnAppearing,或者我只是设置它就在页面构造函数中。
另外,在崩溃行设置断点时,当模板中的显示元素为Label时一切正常,但当显示元素为Image 调试器在尝试查看这些值时冻结。问题显然在于在这种精确情况下调用转换器这一事实。
我通过向模板添加不同的转换器进行了测试:
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="False" Padding="5" HeightRequest="{Binding Path=., Converter={StaticResource PictureNameToHeightConverter}}">
<Label Text="{Binding Path=.}" />
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
完全相同的结果:传递给 Convert 方法的 value 参数为 null,即使在同一个模板实例中具有相同的绑定值显示在标签中。如果我像以前一样在分配 ItemsSource 属性的行上设置断点,调试器将冻结。
更新
最后开始怀疑我在框架中触发了一些极端情况错误,我将 CollectionView 替换为 CarouselView,它可以正常工作:
<CarouselView
x:Name="picturesView"
HeightRequest="90">
<CarouselView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="False" Padding="5">
<Image
HeightRequest="80"
Source="{Binding Path=., Converter={StaticResource PictureNameToImageSourceConverter}}" />
</Frame>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
我将其添加为问题的更新而不是答案,因为我实际上仍然不知道解释。
【问题讨论】:
-
如果您认为转换器导致崩溃,为什么不发布该代码?转换器有异常处理代码吗?
-
我应该澄清一下标题。我不认为转换器导致崩溃。
-
这似乎是我的罪魁祸首。如果您将图像换成标签并且崩溃停止,那么这似乎很重要。您是否检查过日志中的任何相关消息?您是否设置了任何崩溃报告工具?
-
建议:使用
try-catch在转换器内包装代码。在转换器中放置一个断点。和/或转换器中的 Debug.WriteLine。听起来将列表中的一个字符串转换为图像存在一些问题。 -
这是个好主意。从未到达转换器第一行的断点。
标签: xamarin.forms valueconverter