【发布时间】:2020-11-24 12:02:02
【问题描述】:
以前我有一个 ViewModel,它变得非常大,所以我决定将它分散到两个单独的 ViewModel 中。现在我想出了在 ViewModel 之间访问方法的问题。例如,我需要运行现在位于 DataLogModel.cs 中的 UpdateDataGridView();,并且每次更改窗口时我都需要从 ViewModel.cs 运行它(在 ViewModel.cs 中的 WinEventProc 方法内)。
正确的做法是什么?我试过了:
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; }
}
}
DataLogModel.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; }
}
}
【问题讨论】:
-
管理多个视图模型的常用方法是拥有一个具有公共属性的主视图模型,该属性包含对某些子视图模型的引用。
-
@Clemens 我已经添加了 MainViewModel.cs。你是这个意思吗?但是也不可能 ´DataLogModel.UpdateDataGridView();`
-
不知道您在 MainViewModel 中对这些属性究竟做了什么,但当然所有这些属性都应该被初始化,即获得分配的值。然后将 MainViewModel 的一个实例传递给视图的 DataContext。在视图中绑定到子视图模型属性,例如
{Binding DataLogModel.ActivityLogData}"。