首页 > 解决方案 > 从另一个 ViewModel 访问 ViewModel 中的方法

问题描述

以前我有一个 ViewModel,它变得非常大,所以我决定将它分散到两个单独的 ViewModel 中。现在我想出了在 ViewModel 之间访问方法的问题。UpdateDataGridView();例如,我需要运行现在位于其中的示例,DataLogModel.cs并且我需要从ViewModel.cs每次更改窗口时运行它(在 WinEventProc 方法中ViewModel.cs)。

正确的做法是什么?我尝试过:

var DL = new DataLogModel();
DL.UpdateDataGridView();

没有错误,但也没有访问方法(= DataGrid 没有更新)。但是从工作中访问相同的方法DataLogModel.cs就可以了(= DataGrid 已按预期更新)

ViewModel.cs:

using Tracker.Models;
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;

namespace Tracker
{
    public class ChModel
    {
        private string DBconnectionString = ConfigurationManager.AppSettings["DBConnectionString"];

        /// <summary>
        /// We are interested to display only Today data in Chart
        /// /// <summary>
        public DataTable GetDataForChart()
        {
            DataTable ndt = new DataTable();
            SqlConnection sqlcon = new SqlConnection(DBconnectionString);
            ...
            return ndt;
        }
    }

    class ViewModel : BaseViewModel
    {
        private GetActiveWindowTitle.WinEventDelegate dele = null;

        long milliSeconds;
        TimeSpan timeSpan;
        DateTime CurrentDate;

        public static string WindowTitle;
        public static Stopwatch stopwatch = new Stopwatch();
        public static Stopwatch ManualStopwatch = new Stopwatch();

        public ViewModel()
        {
            // Let's start tracking windows
            StartWindowTracking();

        }

        /// <summary>
        /// Track windows
        /// <summary>
        private void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd,
            int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
        {
            WindowTitle = GetActiveWindowTitle.GetActiveWindowTitleMethod();

            if (!string.IsNullOrEmpty(WindowTitle))
            {
                stopwatch.Stop();

                milliSeconds = stopwatch.ElapsedMilliseconds;
                timeSpan = stopwatch.Elapsed;
                CurrentDate = DateTime.Now;

                MainProcess.AddRecordToDatatable(WindowTitle,
                            (int)(milliSeconds / 1000), DateTime.Now.Date, MainProcess.AdminHoursCode, MainProcess.userName);

                UpdateDataGridView();

                stopwatch.Start();
            }

        }

        public void StartWindowTracking()
        {
            WindowTitle = GetActiveWindowTitle.GetActiveWindowTitleMethod();

            dele = new GetActiveWindowTitle.WinEventDelegate(WinEventProc);
            IntPtr m_hhook = GetActiveWindowTitle.SetWinEventHook(GetActiveWindowTitle.EVENT_OBJECT_FOCUS,
                GetActiveWindowTitle.EVENT_OBJECT_FOCUS, IntPtr.Zero, dele, 0, 0, GetActiveWindowTitle.WINEVENT_OUTOFCONTEXT);
        }

        public string DBconnectionString { get; internal set; }
    }
}

数据日志模型.cs:

using Tracker.Models;
using System;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;

namespace Tracker
{
    public class Model
    {
        private string DBconnectionString1 = ConfigurationManager.AppSettings["DBConnectionString"];

        /// <summary>
        /// Get data according to StartDate value
        /// <summary>
        public DataTable GetData(DateTime MyDate)
        {
            DataTable ndt = new DataTable();
            SqlConnection sqlcon = new SqlConnection(DBconnectionString1);
            ...
            return ndt;
        }
    }
    class DataLogModel : BaseViewModel
    {

        public DataLogModel()
        {
            // Update DataGrid
            UpdateDataGridView();
        }

        Model _myModel = new Model();
        private ObservableCollection<ActivityLogModel> _activityLogData = new ObservableCollection<ActivityLogModel>();
        public ObservableCollection<ActivityLogModel> ActivityLogData
        {
            get { return _activityLogData; }
            set
            {
                _activityLogData = value;
                OnPropertyChanged();
            }
        }

        public void UpdateDataGridView()
        {
            DataTable table = _myModel.GetData(StartDate);

            ActivityLogData.Clear();

            for (int i = 0; i < table.Rows.Count; ++i)
                ActivityLogData.Add(new ActivityLogModel
                {
                    WindowTitle = table.Rows[i][0].ToString(),
                    TimeSpent = (int)table.Rows[i][1],
                    DateToday = Convert.ToDateTime(table.Rows[i][2]),
                    Project = table.Rows[i][3].ToString(),
                    UserName = table.Rows[i][4].ToString(),
                });
        }
    }
}

MainViewModel.cs:

using Tracker.Models;
using System.Windows;
using System.Windows.Input;

namespace Tracker
{
    class MainViewModel
    {
        public WindowViewModel WindowViewModel { get; set; }
        public ViewModel ViewModel { get; set; }
        public SettingsViewModel SettingsViewModel { get; set; }
        public DataLogModel DataLogModel { get; set; }
    }
}

标签: c#wpfmvvmviewmodel

解决方案


var DL = new DataLogModel();
DL.UpdateDataGridView();

此代码的问题在于 DL 是一个“新的”DataLogModel ...它与 DataGrid 所在的 DataLogModel 实例不同,因此它无法以您想要的方式刷新它。

如果您尝试在“正确的”DataLogModel 上调用该方法,您需要的是对该 DataLogModel 的引用。例如,当您创建 ViewModel 和 DataLogModel 时,您会将 DataLogModel 的特定实例传递给 ViewModel(通常在构造函数本身中)以便能够调用它。


推荐阅读