You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Android读取本地XML并绑定XAML遇文件不存在异常求助

Xamarin.Android读取本地XML文件异常修复与数据绑定实现方案

一、「There is no store file.」异常排查与修复

核心问题

  1. 文件路径错误:Xamarin.Android中,项目根目录的文件不会直接映射到应用运行目录,直接用Path.Combine("store.xml")无法找到文件
  2. 文件属性未配置:未正确设置XML文件的生成操作,导致文件未被打包到APK中

修复步骤

1. 配置文件属性

  • 在Visual Studio中选中Store.xml文件,右键打开「属性」面板
  • 将「生成操作」设置为AndroidAsset,「复制到输出目录」设置为「始终复制」

2. 修改文件读取逻辑

Xamarin.Android读取Assets目录文件需使用AssetManager,替换原有的FileStream读取方式:

修改后的ViewModel代码:

public static void StoreLoad()
{
    Dictionary<int, StoreData> newlist = new Dictionary<int, StoreData>();
    XmlTextReader reader;

    try
    {
        // 通过AssetManager获取Assets目录下的文件流
        var assets = Android.App.Application.Context.Assets;
        using (var stream = assets.Open("store.xml"))
        {
            reader = new XmlTextReader(stream);
        }
    }
    catch (FileNotFoundException ex)
    {
        throw new Exception("There is no store file.");
    }
    catch
    {
        throw new Exception("Unable to load store file.");
    }

    try
    {
        reader.Read();
        reader.MoveToContent();
        if (reader.LocalName != "StoreList")
            throw new Exception("Store file is corrupt.");

        reader.Read();
        reader.MoveToContent();
        while (!reader.EOF)
        {
            if (reader.LocalName == "Store")
            {
                int code;
                string name;
                string number;
                int dept = 0;

                code = int.Parse(reader.GetAttribute("Code"));
                number = reader.GetAttribute("Number");
                name = reader.GetAttribute("ShortName");

                string deptStr = reader.GetAttribute("Dept");
                if (deptStr != null && deptStr.Length > 0)
                    dept = int.Parse(deptStr);
                else
                    dept = 0;

                newlist.Add(code, new StoreData(code, number, name, dept));
            }
            reader.Read();
            reader.MoveToContent();
        }

        StoreData = newlist;
    }
    finally
    {
        reader.Close();
    }
}

3. 补充Model构造函数

原StoreData类缺少匹配的带参构造函数,补充后才能正常实例化:

public class StoreData
{  
    // 补充带参构造函数
    public StoreData(int code, string number, string shortName, int dept)
    {
        Code = code;
        Number = number;
        ShortName = shortName;
        Dept = dept;
    }

    public int Code { get; set; }
    public string Number { get; set; }
    public int Dept { get; set; }
    public string ShortName { get; set; }
}

二、XML数据绑定到XAML实现步骤

1. 改造ViewModel实现数据通知

ViewModel需实现INotifyPropertyChanged接口,确保数据变化能同步到UI:

public class StoreViewModel : INotifyPropertyChanged
{
    private Dictionary<int, StoreData> _storeData;
    public Dictionary<int, StoreData> StoreData
    {
        get => _storeData;
        set
        {
            _storeData = value;
            OnPropertyChanged(nameof(StoreData));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    // 将原静态方法改为实例方法,便于绑定上下文调用
    public void StoreLoad()
    {
        Dictionary<int, StoreData> newlist = new Dictionary<int, StoreData>();
        XmlTextReader reader;

        try
        {
            var assets = Android.App.Application.Context.Assets;
            using (var stream = assets.Open("store.xml"))
            {
                reader = new XmlTextReader(stream);
            }
        }
        catch (FileNotFoundException ex)
        {
            throw new Exception("There is no store file.");
        }
        catch
        {
            throw new Exception("Unable to load store file.");
        }

        try
        {
            reader.Read();
            reader.MoveToContent();
            if (reader.LocalName != "StoreList")
                throw new Exception("Store file is corrupt.");

            reader.Read();
            reader.MoveToContent();
            while (!reader.EOF)
            {
                if (reader.LocalName == "Store")
                {
                    int code;
                    string name;
                    string number;
                    int dept = 0;

                    code = int.Parse(reader.GetAttribute("Code"));
                    number = reader.GetAttribute("Number");
                    name = reader.GetAttribute("ShortName");

                    string deptStr = reader.GetAttribute("Dept");
                    if (deptStr != null && deptStr.Length > 0)
                        dept = int.Parse(deptStr);
                    else
                        dept = 0;

                    newlist.Add(code, new StoreData(code, number, name, dept));
                }
                reader.Read();
                reader.MoveToContent();
            }

            StoreData = newlist;
        }
        finally
        {
            reader.Close();
        }
    }
}

2. 在XAML中配置绑定上下文与UI展示

以MainPage.xaml为例,设置绑定上下文并使用ListView展示数据:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:你的应用命名空间"
             x:Class="你的应用命名空间.MainPage">
    <ContentPage.BindingContext>
        <local:StoreViewModel />
    </ContentPage.BindingContext>

    <!-- 绑定Dictionary的Values集合作为ListView数据源 -->
    <ListView ItemsSource="{Binding StoreData.Values}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Orientation="Horizontal" Padding="10">
                        <Label Text="{Binding Code}" WidthRequest="50"/>
                        <Label Text="{Binding ShortName}" WidthRequest="150"/>
                        <Label Text="{Binding Number}" WidthRequest="100"/>
                        <Label Text="{Binding Dept}" WidthRequest="50"/>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

3. 在页面代码中触发数据加载

在MainPage.xaml.cs中调用ViewModel的加载方法:

public MainPage()
{
    InitializeComponent();
    var viewModel = (StoreViewModel)BindingContext;
    viewModel.StoreLoad();
}

内容的提问来源于stack exchange,提问作者Raj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 23:15:45