LoginWindow com Caliburn + MEF MVVM WPF
Pergunta
tentando usar uma janela de login com caliburn + mef
Eu também recebo esses dois avisos
Warning 1 CA2000 : Microsoft.Reliability : In method 'AppBootstrapper.CreateContainer()', call System.IDisposable.Dispose on object 'container' before all references to it are out of scope. C:\adl\DotNetProjects\CaliburnTest\CaliburnTest\AppBootstrapper.cs 25 CaliburnTest
Warning 2 CA2000 : Microsoft.Reliability : In method 'AppBootstrapper.CreateContainer()', call System.IDisposable.Dispose on object 'new AggregateCatalog(Enumerable.Select<Assembly, AssemblyCatalog>(this.SelectAssemblies(), AppBootstrapper.CS$<>9__CachedAnonymousMethodDelegate1))' before all references to it are out of scope. C:\adl\DotNetProjects\CaliburnTest\CaliburnTest\AppBootstrapper.cs 25 CaliburnTest
Agradeço antecipadamente, sei que o caliburn vai me poupar muito tempo. Adoraria fazer isso funcionar!
Neste projeto, meu IShell é uma interface vazia.
public class AppBootstrapper : Bootstrapper<IShell>
{
protected override IServiceLocator CreateContainer()
{
var container = new CompositionContainer(
new AggregateCatalog(SelectAssemblies().Select(x => new AssemblyCatalog(x)))
);
var batch = new CompositionBatch();
//batch.AddExportedValue<IWindowManager>(new WindowManager());
return new MEFAdapter(container);
}
}
[Export(typeof(IShell))]
public class MainViewModel : Conductor<IScreen>, IShell
{
readonly IWindowManager windowManager;
[ImportingConstructor]
public MainViewModel(IWindowManager windowManager)
{
this.windowManager = windowManager;
var result = windowManager.ShowDialog(new LoginWindowViewModel());
if (result != true)
{
Application.Current.Shutdown();
}
}
}
[Export(typeof(LoginWindowViewModel))]
public class LoginWindowViewModel :Screen
{
public LoginWindowViewModel()
{
}
public ObservableCollection<User> Users
{
get
{
if (_users == null)
{
_users = new ObservableCollection<User>(){new User("ADMIN","ADMIN","ADMIN")};
}
return _users;
}
}
public bool AuthenticateUser(string username, string pass)
{
Common.Authenticated.CurrentUser = Users.Where<User>(y => y.Login.Trim() == username.Trim()).FirstOrDefault(y => y.Pass.Trim() == pass.Trim());
if (Common.Authenticated.CurrentUser != null)
return true;
return false;
}
public bool Authenticated
{
get
{
if (Username == null || Username == String.Empty || Password == null || Password == String.Empty)
return false;
return AuthenticateUser(Username, Password);
}
}
public bool CheckAuthNeeded() {return true;}
private ObservableCollection<User> _users;
public void Login()
{ RequestClose(this, new SuccessEventArgs(true)); }
public string Username {get;set;}
public string Password {get;set;}
public event CloseDialogEventHandler RequestClose;
public delegate void CloseDialogEventHandler(object sender, SuccessEventArgs e);
}
<"LoginWindowView:
<Grid Height="Auto" Width="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="93*" />
<ColumnDefinition Width="185*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Margin="10,10,0,0">
<Label Content="Username:" FontWeight="Bold" VerticalContentAlignment="Center" Margin="0,4,0,0" Padding="5,5,0,5" />
<Label Content="Password:" FontWeight="Bold" VerticalContentAlignment="Center" VerticalAlignment="Stretch" Margin="0,4,0,0" Padding="5,5,0,5" />
</StackPanel>
<StackPanel Grid.Column="1" Margin="0,10,10,0">
<dxe:ComboBoxEdit x:Name="User" ItemsSource="{Binding Users}"
Padding="0" Margin="5" DisplayMember="Login" ValueMember="Login" Validate="User_Validate" ValidateOnTextInput="True"
AutoComplete="True" ImmediatePopup="True" IncrementalFiltering="True" ShowEditorButtons="False" />
<dxe:PasswordBoxEdit x:Name="Pass" Margin="5" Validate="Pass_Validate" ValidateOnTextInput="False" InvalidValueBehavior="AllowLeaveEditor" />
</StackPanel>
<Button Content="Login" Grid.Row="1" Height="23" HorizontalAlignment="Center"
x:Name="Login" VerticalAlignment="Top" Width="75" IsDefault="True" Grid.ColumnSpan="2" />
</Grid>
LoginWindowView CodeBehind:
public partial class LoginWindowView
{
public LoginWindowView()
{
InitializeComponent();
}
private void User_Validate(object sender, ValidationEventArgs e)
{
if (e.Value == null)
{
e.IsValid = false;
return;
}
var _vm = GetDataContext();
var u = _vm.Users.FirstOrDefault<User>(x => x.Login.Trim() == ((string)e.Value).Trim().ToUpper());
if (u == null)
{
e.SetError("Invalid Login Name", DevExpress.XtraEditors.DXErrorProvider.ErrorType.Information);
_vm.Username = string.Empty;
e.IsValid = false;
}
else
_vm.Username = User.Text;
}
public LoginWindowViewModel GetDataContext()
{
return (LoginWindowViewModel)DataContext;
}
private void Pass_Validate(object sender, ValidationEventArgs e)
{
if (e.Value == null)
{
e.IsValid = false;
return;
}
var _vm = GetDataContext();
_vm.Password = ((string)e.Value).ToUpper();
if (_vm.Authenticated == false)
{
e.SetError("Wrong Password.", DevExpress.XtraEditors.DXErrorProvider.ErrorType.Critical);
e.IsValid = false;
}
}
private void Window_Closed(object sender, EventArgs ee)
{
GetDataContext().RequestClose -= (s, e) =>
{
this.DialogResult = e.Success;
};
}
private void Window_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (e.OldValue != null)
{
((LoginWindowViewModel)e.OldValue).RequestClose -= (s, ee) =>
{
this.DialogResult = ee.Success;
};
}
((LoginWindowViewModel)e.NewValue).RequestClose += (s, ee) =>
{
this.DialogResult = ee.Success;
};
}
}
public class User
{
public string FullName { get; private set; }
public string Login { get; private set; }
public string Pass { get; private set; }
public User(string fullName, string login, string pass) { FullName = fullName; Login = login; Pass = pass; }
public static User CreateUser(string fullName, string login,string pass)
{
return new User(fullName, login,pass);
}
}
public static class Authenticated
{
public static string AuthString { get; set; }
public static User CurrentUser { get; set; }
public static string UserId
{
get
{
if (CurrentUser != null)
return CurrentUser.Login;
return string.Empty;
}
}
}
<✓MainView:
<Window x:Class="CaliburnTest.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainView" Height="300" Width="300">
<Grid>
<Label>Test</Label>
</Grid>
</Window>
Solução
Na verdade, Rob Eisenberg de Caliburn foi muito útil e ele me ajudou com essa questão.
O problema foi que quando eu mudei para o CALIBURN, o LogInview foi a primeira janela a ser aberta e foi fechada antes que a janela principal foi aberta.
Windows trata a primeira janela aberta como o mainwindow.e quando o mainwindow é fechado verificações do Windows se outras janelas estão abertas, caso não feche o aplicativo.
Ele forneceu uma possível solução de fazer o loginviewModel o shell e fechando-o após abrir o manualVemmodel.