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

Xamarin Forms MVVM模式下UWP平台ListView绑定失效问题

解决Xamarin.Forms MVVM中ListView绑定失效的问题

让我们一步步排查你的问题,核心原因出在INotifyPropertyChanged的错误实现上,还有几个次要的绑定细节需要修正:

1. 致命错误:INotifyPropertyChanged事件被空实现覆盖

在你的ViewModel里,你显式实现了接口的PropertyChanged事件,但这个实现是空的:

event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
    add { }
    remove { }
}

这会导致页面绑定订阅的接口事件没有任何实际的订阅逻辑,即使你调用OnPropertyChanged("ObjPizzaList"),页面也接收不到任何通知——这就是ListView绑定失效的根本原因。

解决方法:直接删除这段代码,因为你已经定义了public的PropertyChanged事件,接口会自动使用这个公共事件。

2. 建议:用ObservableCollection替代List

虽然你是直接给ObjPizzaList赋值整个列表,但List<T>本身不会自动通知集合元素的变化(比如后续添加/删除项)。换成ObservableCollection<XmlPizzaDetails>更符合MVVM的规范,它会自动触发集合变化的通知:

修改ViewModel里的字段和属性:

// 替换List为ObservableCollection
ObservableCollection<XmlPizzaDetails> _objPizzaList;

public ObservableCollection<XmlPizzaDetails> ObjPizzaList
{
    get { return _objPizzaList; }
    set
    {
        if (_objPizzaList != value)
        {
            _objPizzaList = value;
            // 用nameof代替硬编码字符串,避免拼写错误
            OnPropertyChanged(nameof(ObjPizzaList));
        }
    }
}

然后在GetRequest里初始化:

ObjPizzaList = new ObservableCollection<XmlPizzaDetails>();

3. 修正属性的setter:触发PropertyChanged通知

你其他属性(比如Progress、CusButtonText)的setter没有调用OnPropertyChanged,这会导致这些属性的绑定也无法实时更新(比如你的ActivityIndicator可能不会显示加载状态,按钮文本修改后也不会更新)。

以Progress为例,修改setter:

bool _progress;
public bool Progress
{
    get { return _progress; }
    set 
    { 
        if (_progress != value)
        {
            _progress = value;
            OnPropertyChanged(nameof(Progress));
        }
    }
}

同样的,把CusButtonText、SelectedDescription等属性的setter都改成这种形式。

4. 优化异步方法:避免async void在构造函数中使用

你的GetRequest是async void方法,在构造函数中调用async void可能导致异常无法被捕获,建议改成async Task,然后在构造函数中用如下方式调用:

public ViewModel ()
{
    // 用_ = 忽略返回的Task,避免编译器警告
    _ = GetRequest();
}

// 修改方法签名为async Task
public async Task GetRequest()
{
    if (NetworkCheck.IsInternet())
    {
        // 先设置Progress为true,显示加载指示器
        Progress = true;
        Uri geturi = new Uri("http://api.androidhive.info/pizza/?format=xml");
        HttpClient client = new HttpClient();
        HttpResponseMessage responseGet = await client.GetAsync(geturi);
        string response = await responseGet.Content.ReadAsStringAsync();

        //Xml Parsing
        ObjPizzaList = new ObservableCollection<XmlPizzaDetails>();
        XDocument doc = XDocument.Parse(response);
        foreach (var item in doc.Descendants("item"))
        {
            XmlPizzaDetails ObjPizzaItem = new XmlPizzaDetails();
            ObjPizzaItem.ID = item.Element("id").Value.ToString();
            ObjPizzaItem.Name = item.Element("name").Value.ToString();
            ObjPizzaItem.Cost = item.Element("cost").Value.ToString();
            ObjPizzaItem.Description = item.Element("description").Value.ToString();
            ObjPizzaList.Add(ObjPizzaItem);
        }
        Progress = false;
    }
}

最后验证

做完这些修改后,你的ListView应该能正常绑定到ViewModel的ObjPizzaList了,同时其他控件的绑定也会正常工作。另外要确保你的XmlPizzaDetails类的属性都是public的(从你后台设置ItemSource有效来看,这个应该没问题)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:56:30