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

如何在WPF MVVM项目中创建全局数据并实现跨视图同步

WPF MVVM 多视图共享数据解决方案

针对你的场景,有两种实用的实现方案,都能解决日期同步和数据更新的需求:


方案一:共享服务(推荐,解耦性强)

创建一个全局的日期服务,所有需要同步日期的ViewModel都订阅这个服务的变化,适合未来扩展多视图共享数据的场景。

1. 实现日期共享服务

创建DateSelectionService类,实现INotifyPropertyChanged以通知订阅者日期变化:

public class DateSelectionService : INotifyPropertyChanged
{
    // 单例实例,全局可访问
    public static DateSelectionService Instance { get; set; }

    private DateTime _selectedDate;
    public DateTime SelectedDate
    {
        get => _selectedDate;
        set
        {
            if (_selectedDate != value)
            {
                _selectedDate = value;
                OnPropertyChanged(nameof(SelectedDate));
            }
        }
    }

    public DateSelectionService()
    {
        SelectedDate = DateTime.Today; // 默认加载当日日期
    }

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

2. 初始化服务

在App.xaml.cs的启动方法中初始化单例:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        DateSelectionService.Instance = new DateSelectionService();
    }
}

3. 日历ViewModel(View1VM)绑定服务

监听服务日期变化,同时将日历选择同步到服务:

public class View1ViewModel : INotifyPropertyChanged
{
    private readonly DateSelectionService _dateService;
    private DateTime _calendarSelectedDate;

    public DateTime CalendarSelectedDate
    {
        get => _calendarSelectedDate;
        set
        {
            if (_calendarSelectedDate != value)
            {
                _calendarSelectedDate = value;
                _dateService.SelectedDate = value; // 同步到全局服务
                OnPropertyChanged(nameof(CalendarSelectedDate));
            }
        }
    }

    public View1ViewModel()
    {
        _dateService = DateSelectionService.Instance;
        _calendarSelectedDate = _dateService.SelectedDate;
        // 监听服务日期变化,同步日历显示
        _dateService.PropertyChanged += DateService_PropertyChanged;
    }

    private void DateService_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(DateSelectionService.SelectedDate))
        {
            CalendarSelectedDate = _dateService.SelectedDate;
        }
    }

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

4. 操作项ViewModel(View3VM)绑定服务

监听日期变化,自动调用API更新数据:

public class View3ViewModel : INotifyPropertyChanged
{
    private readonly DateSelectionService _dateService;
    private ObservableCollection<OperationItem> _operationItems;

    public ObservableCollection<OperationItem> OperationItems
    {
        get => _operationItems;
        set
        {
            _operationItems = value;
            OnPropertyChanged(nameof(OperationItems));
        }
    }

    public View3ViewModel()
    {
        _dateService = DateSelectionService.Instance;
        LoadOperationItems(_dateService.SelectedDate); // 初始加载数据
        _dateService.PropertyChanged += DateService_PropertyChanged;
    }

    private async void DateService_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(DateSelectionService.SelectedDate))
        {
            await LoadOperationItems(_dateService.SelectedDate);
        }
    }

    // API调用逻辑
    private async Task LoadOperationItems(DateTime selectedDate)
    {
        var apiData = await YourApiClient.GetDailyOperations(selectedDate);
        OperationItems = new ObservableCollection<OperationItem>(apiData);
    }

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

5. XAML绑定

View1的日历控件绑定:

<Calendar SelectedDate="{Binding CalendarSelectedDate, Mode=TwoWay}" />

View3的操作项列表绑定:

<ListBox ItemsSource="{Binding OperationItems}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ItemName}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

方案二:父ViewModel传递数据(直观,适合小型项目)

用HomepageViewModel作为父ViewModel,持有子ViewModel实例,直接传递日期数据,新手更容易理解。

1. 父ViewModel(HomepageVM)

维护共享日期,同步给子VM:

public class HomepageViewModel : INotifyPropertyChanged
{
    private DateTime _selectedDate;
    public DateTime SelectedDate
    {
        get => _selectedDate;
        set
        {
            if (_selectedDate != value)
            {
                _selectedDate = value;
                OnPropertyChanged(nameof(SelectedDate));
                View1VM.CalendarSelectedDate = value;
                _ = View3VM.LoadOperationItems(value);
            }
        }
    }

    public View1ViewModel View1VM { get; }
    public View3ViewModel View3VM { get; }

    public HomepageViewModel()
    {
        SelectedDate = DateTime.Today;
        View1VM = new View1ViewModel(SelectedDate);
        View3VM = new View3ViewModel(SelectedDate);
        // 监听子VM的日历变化,同步到父VM
        View1VM.PropertyChanged += View1VM_PropertyChanged;
    }

    private void View1VM_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(View1ViewModel.CalendarSelectedDate))
        {
            SelectedDate = View1VM.CalendarSelectedDate;
        }
    }

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

2. 子ViewModel调整

View1VM接收初始日期:

public class View1ViewModel : INotifyPropertyChanged
{
    private DateTime _calendarSelectedDate;
    public DateTime CalendarSelectedDate
    {
        get => _calendarSelectedDate;
        set
        {
            if (_calendarSelectedDate != value)
            {
                _calendarSelectedDate = value;
                OnPropertyChanged(nameof(CalendarSelectedDate));
            }
        }
    }

    public View1ViewModel(DateTime initialDate)
    {
        CalendarSelectedDate = initialDate;
    }

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

View3VM提供公开的数据加载方法:

public class View3ViewModel : INotifyPropertyChanged
{
    private ObservableCollection<OperationItem> _operationItems;
    public ObservableCollection<OperationItem> OperationItems
    {
        get => _operationItems;
        set
        {
            _operationItems = value;
            OnPropertyChanged(nameof(OperationItems));
        }
    }

    public View3ViewModel(DateTime initialDate)
    {
        LoadOperationItems(initialDate);
    }

    public async Task LoadOperationItems(DateTime selectedDate)
    {
        var apiData = await YourApiClient.GetDailyOperations(selectedDate);
        OperationItems = new ObservableCollection<OperationItem>(apiData);
    }

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

3. Homepage.xaml绑定子VM

<Grid>
    <local:View1 DataContext="{Binding View1VM}" />
    <local:View3 DataContext="{Binding View3VM}" />
</Grid>

方案选择建议

  • 若项目未来可能扩展更多共享数据场景,优先选共享服务方案,解耦性更强;
  • 若项目规模小、逻辑简单,父VM传递方案更直观,上手更快。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 14:52:17