【发布时间】:2019-04-19 02:55:34
【问题描述】:
我已经使用 MVVM Light 构建了一个小型应用程序,并且我已经达到了需要在我的应用程序中的几个不同 ViewModel 之间传递参数的地步。我已经探索了几种不同的选择,但我真的不是它们的忠实粉丝。到目前为止,我遇到的最有希望的是在 ViewModel 之间传递消息,但这有点限制,因为应用程序有可能同时打开多个相同的 View,我需要将参数隔离到单个实例视图/视图模型。
我目前没有使用 MVVM Light 提供的内置 INavigationService,但我已经做了一个非常相似的(如果我能解决参数注入,我可能会切换)。
这是我的导航服务的精简版:
public class NavigationService : INavigationService
{
/* this implementation will not allow us to have the same window open
more than once. However, for this application, that should be sufficient.
*/
public NavigationService()
{
_openPages = new Dictionary<string, Window>();
}
private readonly Dictionary<string, Window> _openPages;
public void ClosePage(string pageKey)
{
if (!_openPages.ContainsKey(pageKey)) return;
var window = _openPages[pageKey];
window.Close();
_openPages.Remove(pageKey);
}
public IEnumerable<string> OpenPages => _openPages.Keys;
public void NavigateTo(string pageKey)
{
if (!AllPages.ContainsKey(pageKey))
throw new InvalidPageException(pageKey);
// Don't re-open a window that's already open
if (_openPages.ContainsKey(pageKey))
{
_openPages[pageKey].Activate();
return;
}
var page = (Window) Activator.CreateInstance(AllPages[pageKey]);
page.Show();
page.Closed += OnWindowClosedHandler;
_openPages.Add(pageKey, page);
}
// Probably a better way to remove this.
private void OnWindowClosedHandler(object sender, EventArgs args)
{
foreach (var item in _openPages.Where(kvp => kvp.Value == sender).ToList())
{
_openPages.Remove(item.Key);
}
}
// Reflection might work for this.
// Might also consider making this more dynamic so it isn't hard-coded into my service
private readonly Dictionary<string, Type> AllPages = new Dictionary<string, Type>
{
["AddPatientView"] = typeof(AddPatientView),
["CheckInView"] = typeof(CheckInView),
["MainView"] = typeof(MainWindow),
["PatientLookupView"] = typeof(PatientLookupView),
["PatientDetailsView"] = typeof(PatientDetailsView)
};
}
我的大多数 ViewModel 都使用依赖注入来连接其他注入的服务,如下所示:
public class CheckInViewModel : ViewModelBase
{
public CheckInViewModel(ILicenseValidationService licenseValidationService,
IPatientFetchService patientFetchService,
IPatientCheckInService patientCheckInService)
{
if (IsInDesignMode)
{
Title = "Find Member (Design)";
}
else
{
Title = "Find Member";
CanFetch = true;
FindMemberCommand = new RelayCommand(async () => await FindMemberHandler(), () => CanFetch);
CheckInPatientCommand = new RelayCommand<Window>(async (window) => await CheckInPatientHandler(window),
(window) => Patient?.PatientId != null);
_licenseValidationService = licenseValidationService;
_patientFetchService = patientFetchService;
_patientCheckInService = patientCheckInService;
}
}
}
我想实现一些在注入服务的同时注入其他参数的方法。有没有以相对简单的方式完成类似的事情?
【问题讨论】:
-
你考虑过使用di来提供参数吗?它们似乎是依赖关系。 Fwiw 我更喜欢单窗口应用程序。使用多窗口,用户很容易“丢失”一两个。
-
@Andy DI 是一个选项,但我不确定如何在不定义某种静态服务的情况下将参数动态注入构造函数。
标签: c# wpf mvvm dependency-injection mvvm-light