Xamarin.Forms绑定异常:点击按钮跳转后新页面无内容显示
Xamarin.Forms 页面无法显示嵌入资源图片与文本的问题修复
核心问题分析与修复步骤
1. 绑定上下文与数据类型不匹配
XAML中设置了x:DataType="models:Mem",但页面的BindingContext是MemViewModel,直接绑定imageSource、interpretation会找不到对应属性——这些属性实际在MemViewModel的Mem对象里。
错误绑定代码:
<Image Source="{Binding imageSource}" .../> <Label Text="{Binding interpretation}" .../>
修复后XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:models="clr-namespace:MDivination.Models" xmlns:viewmodels="clr-namespace:MDivination.ViewModels" x:DataType="viewmodels:MemViewModel" <!-- 修正数据类型为ViewModel --> x:Class="MDivination.Views.DivinationResult"> <ContentPage.Content> <StackLayout> <!-- 绑定路径改为ViewModel中的Mem对象属性 --> <Image Source="{Binding Mem.imageSource}" Aspect="AspectFit" VerticalOptions="Center" HorizontalOptions="Center" HeightRequest="100" WidthRequest="100"/> <Label Text="{Binding Mem.interpretation}" VerticalOptions="Center" HorizontalOptions="Center" TextColor="Purple"/> </StackLayout> </ContentPage.Content> </ContentPage>
同时删除XAML中重复设置的<ContentPage.BindingContext>节点,保留页面构造函数的BindingContext赋值即可,避免冲突。
2. Mem类属性的无限递归与初始化错误
Mem类的属性存在无限递归(get返回自身),且资源加载逻辑写在setter里但从未被触发,导致属性值始终为null。
错误的Mem类属性:
public int id { get { return id; } // 无限递归,直接返回自身 set { Random random = new Random(); id = random.Next(0,2); OnPropertyChanged(nameof(id)); } } public ImageSource imageSource { get { return imageSource; } // 同样递归 set { var assembly = IntrospectionExtensions.GetTypeInfo(typeof(MemViewModel)).Assembly; imageSource = ImageSource.FromResource($"MDivination.Images.{id}.png"); OnPropertyChanged(nameof(imageSource)); } }
修复后的Mem类:
namespace MDivination.Models { public class Mem : INotifyPropertyChanged { // 用私有字段存储值,避免递归 private int _id; private ImageSource _imageSource; private string _interpretation; private string _history; public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string name) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } public Mem() { // 构造函数中直接初始化随机ID并加载资源 Random random = new Random(); _id = random.Next(0, 2); LoadImage(); LoadInterpretation(); } public int id { get { return _id; } set { _id = value; OnPropertyChanged(nameof(id)); // ID变化时重新加载资源 LoadImage(); LoadInterpretation(); } } public ImageSource imageSource { get { return _imageSource; } private set { _imageSource = value; OnPropertyChanged(nameof(imageSource)); } } public string interpretation { get { return _interpretation; } private set { _interpretation = value; OnPropertyChanged(nameof(interpretation)); } } public string history { get { return _history; } private set { _history = value; OnPropertyChanged(nameof(history)); } } // 封装资源加载逻辑,避免重复代码 private void LoadImage() { var assembly = IntrospectionExtensions.GetTypeInfo(typeof(Mem)).Assembly; imageSource = ImageSource.FromResource($"MDivination.Images.{_id}.png"); } private void LoadInterpretation() { var assembly = IntrospectionExtensions.GetTypeInfo(typeof(Mem)).Assembly; // 加空判断,避免资源不存在时崩溃 using (Stream stream = assembly.GetManifestResourceStream($"MDivination.Interpretation.{_id}.txt")) { interpretation = stream != null ? new StreamReader(stream).ReadToEnd() : "资源未找到"; } } } }
3. 嵌入资源的生成操作验证
确保图片和文本文件的生成操作设置为Embedded Resource,且资源命名空间与代码中的路径一致:
- 图片路径示例:
MDivination.Images.0.png、MDivination.Images.1.png - 文本路径示例:
MDivination.Interpretation.0.txt、MDivination.Interpretation.1.txt
可以通过以下代码输出所有嵌入资源名称,检查路径是否正确:
// 在LoadImage方法中添加调试代码 var assembly = IntrospectionExtensions.GetTypeInfo(typeof(Mem)).Assembly; var resourceNames = assembly.GetManifestResourceNames(); foreach (var name in resourceNames) { System.Diagnostics.Debug.WriteLine(name); }
4. ViewModel的Navigation属性初始化
确保MemViewModel的Navigation属性在跳转前被赋值,比如在主页面构造函数中:
// 主页面代码示例 public MainPage() { InitializeComponent(); var vm = new MemViewModel(); vm.Navigation = Navigation; BindingContext = vm; }
内容的提问来源于stack exchange,提问作者Евгений Дельфонцев
相关产品推荐
相关产品推荐

