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

Xamarin.Forms:Application类绑定ObservableCollection到ListView无显示问题

问题分析与解决方案

你遇到的核心问题是:App类的XAML并不是应用可视化UI的一部分,你在App.xaml中定义的ListView根本不会被渲染到屏幕上——App本身是应用的入口管理类,不是Page类型,它的XAML内容不会被加入到应用的可视化树中,这也是为什么相同代码在Main.xaml里能正常运行的原因。

具体修复步骤

1. 移除App.xaml中的ListView代码

首先把App.xaml里的测试ListView代码删掉,App的XAML应该只保留应用级别的资源定义,不要放可视化UI元素:

<!-- App.xaml 现在只保留必要内容 -->
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HOT_App.App">
    <Application.Resources>
        <!-- 这里放应用级资源,比如样式、颜色等 -->
    </Application.Resources>
</Application>

2. 将导航ListView移到页面中(比如Main.xaml)

把之前的ListView代码放到你的根页面(比如Main.xaml)里,或者创建一个专门的导航布局页面。示例如下:

<!-- Main.xaml -->
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HOT_App.Views.Main">
    <StackLayout>
        <!-- 导航ListView -->
        <ListView ItemsSource="{Binding NavigationItemss}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Horizontal">
                            <Label Text="{Binding Icon}" />
                            <Label Text="{Binding NavigationItemName}" />
                            <!-- 可以根据Active状态设置样式,比如高亮 -->
                            <BoxView WidthRequest="10" HeightRequest="10" 
                                     Color="{Binding Active, Converter={StaticResource BoolToColorConverter}}"
                                     Margin="0,0,10,0"/>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <!-- 页面其他内容 -->
        <Label Text="主页面内容" />
    </StackLayout>
</ContentPage>

3. 确保Navigation类实现INotifyPropertyChanged

你的Navigation类目前没有实现INotifyPropertyChanged接口,虽然ObservableCollection本身会通知集合变化,但如果后续需要修改类中的属性(比如Active状态的变化要实时更新UI),需要接口支持。修改Navigation.cs:

using HOT_App.Views;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Xamarin.Forms;

namespace HOT_App.ViewModels {
    // 实现INotifyPropertyChanged接口
    class Navigation : INotifyPropertyChanged {
        public ObservableCollection<NavigationItem> NavigationItemss { get; set; }

        public Navigation() {
            NavigationItemss = new ObservableCollection<NavigationItem>();
            NavigationItem Home = new NavigationItem("Home","NavigationHome.png",true);
            NavigationItem Trends = new NavigationItem("Trends","NavigationTrend.png",false);
            NavigationItemss.Add(Home);
            NavigationItemss.Add(Trends);
        }

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

        // 你的其他方法:ShowActiveNavigation、SetActiveNavigation、ChangeActiveValue...
        public void ShowActiveNavigation() {
            System.Diagnostics.Debug.WriteLine(string.Join<NavigationItem>("\n", NavigationItemss));
        }

        public void SetActiveNavigation(string activeNavigationName) {
            ChangeActiveValue(activeNavigationName);
            switch (activeNavigationName) {
                case "Home":
                    Application.Current.MainPage.Navigation.PushAsync(new Main(), false);
                    System.Diagnostics.Debug.WriteLine("Home");
                    break;
                case "Trends":
                    Application.Current.MainPage.Navigation.PushAsync(new Trends(), false);
                    System.Diagnostics.Debug.WriteLine("Trends");
                    break;
                default:
                    Application.Current.MainPage.Navigation.PushAsync(new Main(), false);
                    System.Diagnostics.Debug.WriteLine("Home");
                    break;
            }
        }

        public void ChangeActiveValue(string activeNavigationName) {
            foreach(NavigationItem navigationItem in NavigationItemss) {
                if (navigationItem.NavigationItemName == activeNavigationName) {
                    navigationItem.Active = true;
                } else {
                    navigationItem.Active = false;
                }
            }
        }
    }

    // 确保NavigationItem也实现INotifyPropertyChanged,否则Active变化不会更新UI
    class NavigationItem : INotifyPropertyChanged {
        private string _navigationItemName;
        private string _icon;
        private bool _active;

        public string NavigationItemName {
            get => _navigationItemName;
            set {
                _navigationItemName = value;
                OnPropertyChanged();
            }
        }

        public string Icon {
            get => _icon;
            set {
                _icon = value;
                OnPropertyChanged();
            }
        }

        public bool Active {
            get => _active;
            set {
                _active = value;
                OnPropertyChanged();
            }
        }

        public NavigationItem(string name, string icon, bool active) {
            NavigationItemName = name;
            Icon = icon;
            Active = active;
        }

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

4. 在页面的构造函数中设置BindingContext

修改Main.xaml.cs,把Navigation实例作为页面的BindingContext:

namespace HOT_App.Views {
    public partial class Main : ContentPage {
        public Main() {
            InitializeComponent();
            // 设置BindingContext为Navigation实例
            BindingContext = new Navigation();
        }
    }
}

额外建议:使用Xamarin.Forms Shell实现导航

如果你的应用是中等复杂度以上,推荐使用Xamarin.Forms Shell来实现底部/侧边导航,它自带导航管理、路由、底部标签栏等功能,比自己用ListView实现导航更简洁稳定。

比如Shell的基本用法:

<!-- AppShell.xaml -->
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:views="clr-namespace:HOT_App.Views"
       x:Class="HOT_App.AppShell">
    <TabBar>
        <ShellContent Title="Home" Icon="NavigationHome.png" ContentTemplate="{DataTemplate views:Main}" />
        <ShellContent Title="Trends" Icon="NavigationTrend.png" ContentTemplate="{DataTemplate views:Trends}" />
    </TabBar>
</Shell>

然后在App.xaml.cs中设置MainPage为Shell:

public App() {
    InitializeComponent();
    if (UseMockDataStore)
        DependencyService.Register<MockDataStore>();
    else
        DependencyService.Register<AzureDataStore>();
    // 用Shell作为根页面
    MainPage = new AppShell();
}

这样Shell会自动处理导航状态、图标高亮等功能,不需要自己维护ObservableCollection和Active状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:31:20