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

如何将多个ViewModel绑定到单个View?双ListView需各绑定独立ViewModel作ItemsSource

如何将多个ViewModel绑定到单个View?

嘿,这个需求在实际开发中挺常见的,尤其是当一个页面有多个独立的列表模块时。我给你分享两种最常用的实现方式,都是经过项目验证的:

方法一:使用主ViewModel包含子ViewModel(推荐)

这种方式是MVVM模式下的标准做法,通过一个主ViewModel来管理多个子ViewModel,保持代码的结构化和可维护性。

步骤:

  1. 创建子ViewModel:为每个ListView分别定义独立的ViewModel,处理各自的数据逻辑和业务:
public class List1ViewModel : INotifyPropertyChanged
{
    private ObservableCollection<string> _items;
    public ObservableCollection<string> Items
    {
        get => _items;
        set
        {
            _items = value;
            OnPropertyChanged();
        }
    }

    public List1ViewModel()
    {
        // 初始化数据
        Items = new ObservableCollection<string> { "Item 1-1", "Item 1-2", "Item 1-3" };
    }

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

public class List2ViewModel : INotifyPropertyChanged
{
    private ObservableCollection<string> _items;
    public ObservableCollection<string> Items
    {
        get => _items;
        set
        {
            _items = value;
            OnPropertyChanged();
        }
    }

    public List2ViewModel()
    {
        // 初始化数据
        Items = new ObservableCollection<string> { "Item 2-1", "Item 2-2", "Item 2-3" };
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
  1. 创建主ViewModel:在主ViewModel中声明两个子ViewModel的属性:
public class MainPageViewModel : INotifyPropertyChanged
{
    private List1ViewModel _list1VM;
    public List1ViewModel List1VM
    {
        get => _list1VM;
        set
        {
            _list1VM = value;
            OnPropertyChanged();
        }
    }

    private List2ViewModel _list2VM;
    public List2ViewModel List2VM
    {
        get => _list2VM;
        set
        {
            _list2VM = value;
            OnPropertyChanged();
        }
    }

    public MainPageViewModel()
    {
        List1VM = new List1ViewModel();
        List2VM = new List2ViewModel();
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
  1. 在XAML中绑定:将ContentPage的BindingContext设置为主ViewModel,然后每个ListView的ItemsSource绑定到对应的子ViewModel属性:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="YourNamespace.MainPage"
             xmlns:vm="clr-namespace:YourNamespace.ViewModels">
    <ContentPage.BindingContext>
        <vm:MainPageViewModel />
    </ContentPage.BindingContext>

    <StackLayout>
        <ListView ItemsSource="{Binding List1VM.Items}" Margin="10">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding .}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

        <ListView ItemsSource="{Binding List2VM.Items}" Margin="10">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding .}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

方法二:直接为每个ListView设置独立的BindingContext

如果你的页面逻辑比较简单,不想额外创建主ViewModel,可以直接给每个ListView单独指定BindingContext,这种方式更轻量化。

实现方式:

方式A:在XAML中直接实例化ViewModel

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="YourNamespace.MainPage"
             xmlns:vm="clr-namespace:YourNamespace.ViewModels">
    <StackLayout>
        <ListView Margin="10">
            <ListView.BindingContext>
                <vm:List1ViewModel />
            </ListView.BindingContext>
            <ListView.ItemsSource>
                <Binding Path="Items" />
            </ListView.ItemsSource>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding .}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

        <ListView Margin="10">
            <ListView.BindingContext>
                <vm:List2ViewModel />
            </ListView.BindingContext>
            <ListView.ItemsSource>
                <Binding Path="Items" />
            </ListView.ItemsSource>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding .}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

方式B:在后台代码中设置BindingContext

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        listView1.BindingContext = new List1ViewModel();
        listView2.BindingContext = new List2ViewModel();
    }
}

注意事项

  • 不管用哪种方式,所有ViewModel都必须实现INotifyPropertyChanged接口,这样当数据更新时,UI才能自动刷新。
  • 如果使用依赖注入(DI)框架(比如Prism、Maui内置DI),可以通过DI来注入子ViewModel,而不是手动new,这样更符合松耦合的设计原则。
  • 尽量保持每个子ViewModel的职责单一,只处理对应ListView的相关逻辑,避免把所有代码堆在一个ViewModel里。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 09:17:30