#.net #silverlight #mvvm #mvvm-light
#.net #silverlight #mvvm #mvvm-light
Вопрос:
Как обычно, я пытаюсь использовать новую технологию и сразу же сталкиваюсь с проблемами.
У меня есть бизнес-приложение Silverlight MVVMLight.
В моей viewmodel я пытаюсь получить роли зарегистрированных пользователей:
public HomeViewModel()
{
if (IsInDesignMode)
{
// Code runs in Blend --> create design time data.
}
else
{
// Code runs "for real"
DetermineStartableProcesses();
}
}
private void DetermineStartableProcesses()
{
_startableProcesses = new ObservableCollection<WorkflowProcess>(
WebContext.Current.User.Roles.SelectMany(r =>
WorkflowProcess.GetStartableByRole(r))
.Distinct());
}
Во время выполнения я получаю это исключение:
System.Windows.Markup.XamlParseException occurred
Message=The invocation of the constructor on type 'CompanyHR.ViewModel.ViewModelLocator' that matches the specified binding constraints threw an exception. [Line: 18 Position: 57]
LineNumber=18
LinePosition=57
StackTrace:
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
at CompanyHR.App.InitializeComponent()
at CompanyHR.App..ctor()
InnerException: System.ArgumentNullException
Message=Value cannot be null.
Parameter name: source
StackTrace:
at System.Linq.Enumerable.SelectMany[TSource,TResult](IEnumerable`1 source, Func`2 selector)
at CompanyHR.ViewModel.HomeViewModel.DetermineStartableProcesses()
at CompanyHR.ViewModel.HomeViewModel..ctor()
at CompanyHR.ViewModel.ViewModelLocator..ctor()
InnerException:
Похоже, что ViewModelLocator создает экземпляры ViewModels при запуске приложения до создания webcontext get, что означает, что для меня плохая идея выполнять много работы в моих конструкторах viewmodel.
Итак, где в viewmodel я должен извлекать данные, которые будут привязаны к базе данных?
Ответ №1:
Создайте экземпляр вашего WebContext в конструкторе приложения. затем добавьте его к своим ресурсам в App_startup перед вызовом
public App()
{
Startup = Application_Startup;
Exit = Application_Exit;
UnhandledException = Application_UnhandledException;
if (IsInDesignModeStatic)
{
Services.ServiceLoader.LoadDesignTimeServices();
DispatcherHelper.Initialize();
}
else
{
try
{
ServiceLoader.LoadRunTimeServices();
DispatcherHelper.Initialize();
WebContext webContext = new WebContext();
ApplicationLifetimeObjects.Add(WebContext.Current);
FormsAuthentication fa = new FormsAuthentication();
fa.DomainContext = new Web.Services.AuthenticationDomainContext();
WebContext.Current.Authentication = fa;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
InitializeComponent();
}
private void Application_Startup(object sender, StartupEventArgs e)
{
this.Resources.Add("WebContext", WebContext.Current);
RootVisual = new MainPage();
}
Я считаю, что эту часть в коде проще выполнить из-за моего пользовательского AuthenticationDomainContext и Membershipprovider…Но Dereks тоже работает хорошо, я просто использовал исходный код, пока все работало.
Ответ №2:
Вот как я избежал этого при использовании mvvm-light. Итак, WebContext создается первым.
В App.xaml:
<Application.ApplicationLifetimeObjects>
<ct:WebContext>
<ct:WebContext.Authentication>
<as:FormsAuthentication DomainContextType="MyProj.Data.AuthenticationContext, MyProj.Client.Common, Version=1.0.0." />
</ct:WebContext.Authentication>
</ct:WebContext>
</Application.ApplicationLifetimeObjects>
<Application.Resources>
<ResourceDictionary>
<ct:ViewModelLocator x:Key="Locator"
d:IsDataSource="True" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Assets/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>