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

Xamarin.Forms中CollectionView Footer绑定数据实现借贷列合计显示

Xamarin.Forms CollectionView Footer合计显示问题解决方案

你之前的实现失效主要有三个核心原因:

  1. XAML仅支持绑定公共属性,你定义的total等都是字段,无法被识别
  2. Footer的绑定源设置错误,没有将合计对象单独绑定给Footer属性
  3. 没有实现INotifyPropertyChanged接口,异步加载完合计数据后UI无法收到更新通知

具体修复步骤

1. 定义页脚数据模型

确保所有绑定字段都是公共属性:

public class AccountFooter
{
    public string Total { get; set; }
    public decimal Totjvdebit { get; set; }
    public decimal Totjvcredit { get; set; }
    public decimal Totbalance { get; set; }
}

2. 实现带通知的ViewModel

继承INotifyPropertyChanged,同时包含列表和页脚两个数据源:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Collections.ObjectModel;

public class AccountViewModel : INotifyPropertyChanged
{
    // 明细列表数据源,用ObservableCollection支持自动UI刷新
    public ObservableCollection<accountdetails> AccountItems { get; set; } = new ObservableCollection<accountdetails>();
    
    private AccountFooter _footerData;
    // 页脚合计数据源,变更时触发通知
    public AccountFooter FooterData
    {
        get => _footerData;
        set
        {
            _footerData = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

3. 修改XAML绑定配置

调整CollectionView的绑定,将Footer绑定到ViewModel的FooterData属性:

<!-- 把原来的CollectionView标签替换成下面的内容 -->
<CollectionView x:Name="accountdetailslst" 
                ItemsSource="{Binding AccountItems}" 
                Footer="{Binding FooterData}">
    <!-- 其余Header、ItemTemplate、FooterTemplate内容保持不变 -->
</CollectionView>

4. 调整后台逻辑赋值

修改xaml.cs的代码,将加载后的数据赋值给ViewModel的对应属性:

public partial class account_details : ContentPage
{
    AccountViewModel _viewModel;
    public account_details(string acc, string cur, string accname)
    {
        InitializeComponent();
        _viewModel = new AccountViewModel();
        BindingContext = _viewModel;
        // 保留原有图片资源初始化逻辑
        imgAdd.Source = ImageSource.FromResource("isc_alphaApp.remove_ic.png");
        imgfilter.Source = ImageSource.FromResource("isc_alphaApp.filter_ic.png");
        imgshare.Source = ImageSource.FromResource("isc_alphaApp.share_icon.png");
        loadData(acc,cur,accname);
    }

    async private void loadData(string account, string curr,string acc_name )
    {
        acc_curlabel.Text = account + " - " + curr + " - " + acc_name;
        popupLoadingView.IsVisible = true;
        activityIndicator.IsRunning = true;
        HttpClient client = new HttpClient();
        string url = "http://192.168.43.99/siteisc/api/values";
        string uri = url + "/getaccountdetails";
        
        try
        {
            HttpResponseMessage response = await client.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                string content = await response.Content.ReadAsStringAsync();
                var listacc_details = JsonConvert.DeserializeObject<List<allaccountdetails>>(content);
                var list_filtered = listacc_details.FindAll(x => x.JvAccount == account && x.CurrencyCode == curr);
                decimal blnce_row = 0;
                List<String> l = new List<String>();
                for (int i = 0; i < list_filtered.Count; i++)
                {
                    blnce_row = decimal.Parse(list_filtered[i].JvDebit.ToString()) - decimal.Parse(list_filtered[i].Jvcredit.ToString()) + blnce_row;
                    decimal rnd_blnce = Math.Round(blnce_row, 2);
                    l.Add(rnd_blnce.ToString());
                }

                List<accountdetails> listacc_collection = new List<accountdetails>();
                for (int i = 0; i < list_filtered.Count; i++)
                {
                    listacc_collection.Add(new accountdetails { 
                        desc = list_filtered[i].JvDescription, 
                        jvnbr = list_filtered[i].jvnbr.ToString(), 
                        jvcredit = list_filtered[i].Jvcredit.ToString(), 
                        jvdate = DateTime.Parse(list_filtered[i].JvDate).ToString(("dd-M-yyyy")), 
                        jvdebit = list_filtered[i].JvDebit.ToString(), 
                        jvref = list_filtered[i].jvref1, 
                        balance = l[i] 
                    });
                }
                // 给ViewModel的明细列表赋值
                _viewModel.AccountItems.Clear();
                foreach (var item in listacc_collection)
                {
                    _viewModel.AccountItems.Add(item);
                }
                // 计算合计并赋值给FooterData
                var totalDebit = listacc_collection.Sum(x => decimal.Parse(x.jvdebit));
                var totalCredit = listacc_collection.Sum(x => decimal.Parse(x.jvcredit));
                _viewModel.FooterData = new AccountFooter
                {
                    Total = $"Total in {curr}",
                    Totjvdebit = totalDebit,
                    Totjvcredit = totalCredit,
                    Totbalance = totalDebit - totalCredit
                };

                popupLoadingView.IsVisible = false;
                activityIndicator.IsRunning = false;
            }
            else
            {
                await DisplayAlert("Operation Failed", "Response Failed!", "Cancel");
            }
        }
        catch (System.Net.WebException exp)
        {
            await DisplayAlert("Connection Failed", "Please Check Your Internet Connection!", "Cancel");
        }
    }
}

额外注意事项

  • 不要手动给accountdetailslst.ItemsSource赋值,绑定已经关联了AccountItems属性
  • 如果后续需要修改合计值,直接更新FooterData属性即可,UI会自动刷新
  • 可以在FooterTemplate里给数值添加格式化绑定,比如Text="{Binding Totjvdebit, StringFormat='{0:F2}'}"统一显示两位小数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 15:24:00