Saya membuat sebuah Login menggunakan a window control
untuk memungkinkan pengguna login ke WPF
aplikasi yang saya buat.
Sejauh ini, saya telah membuat metode yang memeriksa apakah pengguna telah memasukkan kredensial yang benar untuk username
dan password
di textbox
layar login, binding
dua properties
.
Saya telah mencapai ini dengan membuat bool
metode, seperti;
public bool CheckLogin()
{
var user = context.Users.Where(i => i.Username == this.Username).SingleOrDefault();
if (user == null)
{
MessageBox.Show("Unable to Login, incorrect credentials.");
return false;
}
else if (this.Username == user.Username || this.Password.ToString() == user.Password)
{
MessageBox.Show("Welcome " + user.Username + ", you have successfully logged in.");
return true;
}
else
{
MessageBox.Show("Unable to Login, incorrect credentials.");
return false;
}
}
public ICommand ShowLoginCommand
{
get
{
if (this.showLoginCommand == null)
{
this.showLoginCommand = new RelayCommand(this.LoginExecute, null);
}
return this.showLoginCommand;
}
}
private void LoginExecute()
{
this.CheckLogin();
}
Saya juga memiliki command
yang saya bind
ke tombol saya dalam xaml
seperti itu;
<Button Name="btnLogin" IsDefault="True" Content="Login" Command="{Binding ShowLoginCommand}" />
Ketika saya memasukkan nama pengguna dan kata sandi, ia menjalankan kode yang sesuai, apakah itu benar, atau salah. Tetapi bagaimana saya bisa menutup jendela ini dari ViewModel jika nama pengguna dan kata sandi sudah benar?
Saya sebelumnya telah mencoba menggunakan a dialog modal
tetapi tidak berhasil. Selanjutnya, dalam app.xaml saya, saya telah melakukan sesuatu seperti berikut, yang memuat halaman login terlebih dahulu, kemudian setelah benar, memuat aplikasi sebenarnya.
private void ApplicationStart(object sender, StartupEventArgs e)
{
Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
var dialog = new UserView();
if (dialog.ShowDialog() == true)
{
var mainWindow = new MainWindow();
Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
Current.MainWindow = mainWindow;
mainWindow.Show();
}
else
{
MessageBox.Show("Unable to load application.", "Error", MessageBoxButton.OK);
Current.Shutdown(-1);
}
}
Pertanyaan: Bagaimana cara menutup Login Window control
dari ViewModel?
Terima kasih sebelumnya.
Jawaban:
Anda dapat meneruskan jendela ke ViewModel Anda menggunakan
CommandParameter
. Lihat Contoh saya di bawah ini.Saya telah menerapkan
CloseWindow
Metode yang mengambil Windows sebagai parameter dan menutupnya. Jendela diteruskan ke ViewModel melaluiCommandParameter
. Perhatikan bahwa Anda perlu menentukanx:Name
untuk jendela yang harus ditutup. Di Jendela XAML saya, saya memanggil metode ini melaluiCommand
dan meneruskan jendela itu sendiri sebagai parameter untuk menggunakan ViewModelCommandParameter
.Command="{Binding CloseWindowCommand, Mode=OneWay}" CommandParameter="{Binding ElementName=TestWindow}"
ViewModel
public RelayCommand<Window> CloseWindowCommand { get; private set; } public MainViewModel() { this.CloseWindowCommand = new RelayCommand<Window>(this.CloseWindow); } private void CloseWindow(Window window) { if (window != null) { window.Close(); } }
Melihat
<Window x:Class="ClientLibTestTool.ErrorView" x:Name="TestWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:localization="clr-namespace:ClientLibTestTool.ViewLanguages" DataContext="{Binding Main, Source={StaticResource Locator}}" Title="{x:Static localization:localization.HeaderErrorView}" Height="600" Width="800" ResizeMode="NoResize" WindowStartupLocation="CenterScreen"> <Grid> <Button Content="{x:Static localization:localization.ButtonClose}" Height="30" Width="100" Margin="0,0,10,10" IsCancel="True" VerticalAlignment="Bottom" HorizontalAlignment="Right" Command="{Binding CloseWindowCommand, Mode=OneWay}" CommandParameter="{Binding ElementName=TestWindow}"/> </Grid> </Window>
Perhatikan bahwa saya menggunakan kerangka kerja ringan MVVM, tetapi prinsipnya berlaku untuk setiap aplikasi wpf.
Solusi ini melanggar pola MVVM, karena model tampilan tidak boleh mengetahui apa pun tentang Implementasi UI. Jika Anda ingin mengikuti paradigma pemrograman MVVM secara ketat, Anda harus mengabstraksi jenis tampilan dengan antarmuka.
Solusi sesuai MVVM (Sebelumnya EDIT2)
pengguna Crono menyebutkan poin yang valid di bagian komentar:
Anda dapat memperbaikinya dengan memperkenalkan antarmuka yang berisi metode tutup.
Antarmuka:
public interface ICloseable { void Close(); }
ViewModel Anda yang telah direfraktorisasi akan terlihat seperti ini:
ViewModel
public RelayCommand<ICloseable> CloseWindowCommand { get; private set; } public MainViewModel() { this.CloseWindowCommand = new RelayCommand<IClosable>(this.CloseWindow); } private void CloseWindow(ICloseable window) { if (window != null) { window.Close(); } }
Anda harus mereferensikan dan mengimplementasikan
ICloseable
antarmuka dalam tampilan AndaLihat (Kode di belakang)
public partial class MainWindow : Window, ICloseable { public MainWindow() { InitializeComponent(); } }
Jawaban untuk pertanyaan awal: (sebelumnya EDIT1)
Tombol Login Anda (Menambahkan CommandParameter):
<Button Name="btnLogin" IsDefault="True" Content="Login" Command="{Binding ShowLoginCommand}" CommandParameter="{Binding ElementName=LoginWindow}"/>
Kode Anda:
public RelayCommand<Window> CloseWindowCommand { get; private set; } // the <Window> is important for your solution! public MainViewModel() { //initialize the CloseWindowCommand. Again, mind the <Window> //you don't have to do this in your constructor but it is good practice, thought this.CloseWindowCommand = new RelayCommand<Window>(this.CloseWindow); } public bool CheckLogin(Window loginWindow) //Added loginWindow Parameter { var user = context.Users.Where(i => i.Username == this.Username).SingleOrDefault(); if (user == null) { MessageBox.Show("Unable to Login, incorrect credentials."); return false; } else if (this.Username == user.Username || this.Password.ToString() == user.Password) { MessageBox.Show("Welcome "+ user.Username + ", you have successfully logged in."); this.CloseWindow(loginWindow); //Added call to CloseWindow Method return true; } else { MessageBox.Show("Unable to Login, incorrect credentials."); return false; } } //Added CloseWindow Method private void CloseWindow(Window window) { if (window != null) { window.Close(); } }
sumber
private void LoginExecute(){this.CheckLogin();}
<- CheckLogin perlu menggunakan parameter.CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Window
objek ke model tampilan mematahkan IMHO pola MVVM, karena memaksa vm Anda untuk mengetahui apa yang sedang dilihat. Bagaimana jika tampilan adalah tab yang digalangkan di antarmuka MDI? Cara yang tepat untuk melakukan IMHO ini adalah dengan melewati beberapa jenis antarmuka IUIHost yang mengimplementasikan metode Tutup, dan memiliki tampilan apa pun yang Anda inginkan untuk menunjukkan vm Anda menerapkannya.Saya biasanya meletakkan acara pada model tampilan ketika saya perlu melakukan ini dan kemudian menghubungkannya ke
Window.Close()
saat mengikat model tampilan ke jendelapublic class LoginViewModel { public event EventHandler OnRequestClose; private void Login() { // Login logic here OnRequestClose(this, new EventArgs()); } }
Dan saat membuat jendela login
var vm = new LoginViewModel(); var loginWindow = new LoginWindow { DataContext = vm }; vm.OnRequestClose += (s, e) => loginWindow.Close(); loginWindow.ShowDialog();
sumber
Loaded
,ContentRendered
untuk jendela utama, layanan dialog, dll.), Menambahkan sedikit ke dalamnya melalui acara ViewModel cukup bersih bagi saya. 3 baris kode tidak benar-benar membutuhkan solusi yang dapat digunakan kembali. PS: MVVM murni untuk kutu buku.Tetap MVVM, saya pikir menggunakan Behaviors from the Blend SDK (System.Windows.Interactivity) atau permintaan interaksi khusus dari Prism dapat bekerja sangat baik untuk situasi semacam ini.
Jika mengikuti rute Perilaku, berikut gambaran umumnya:
public class CloseWindowBehavior : Behavior<Window> { public bool CloseTrigger { get { return (bool)GetValue(CloseTriggerProperty); } set { SetValue(CloseTriggerProperty, value); } } public static readonly DependencyProperty CloseTriggerProperty = DependencyProperty.Register("CloseTrigger", typeof(bool), typeof(CloseWindowBehavior), new PropertyMetadata(false, OnCloseTriggerChanged)); private static void OnCloseTriggerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var behavior = d as CloseWindowBehavior; if (behavior != null) { behavior.OnCloseTriggerChanged(); } } private void OnCloseTriggerChanged() { // when closetrigger is true, close the window if (this.CloseTrigger) { this.AssociatedObject.Close(); } } }
Kemudian di jendela Anda, Anda hanya perlu mengikat CloseTrigger ke nilai boolean yang akan disetel saat Anda ingin jendela ditutup.
<Window x:Class="TestApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:local="clr-namespace:TestApp" Title="MainWindow" Height="350" Width="525"> <i:Interaction.Behaviors> <local:CloseWindowBehavior CloseTrigger="{Binding CloseTrigger}" /> </i:Interaction.Behaviors> <Grid> </Grid> </Window>
Terakhir, DataContext / ViewModel Anda akan memiliki properti yang akan Anda setel saat Anda ingin jendela ditutup seperti ini:
public class MainWindowViewModel : INotifyPropertyChanged { private bool closeTrigger; /// <summary> /// Gets or Sets if the main window should be closed /// </summary> public bool CloseTrigger { get { return this.closeTrigger; } set { this.closeTrigger = value; RaisePropertyChanged(nameof(CloseTrigger)); } } public MainWindowViewModel() { // just setting for example, close the window CloseTrigger = true; } protected void RaisePropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public event PropertyChangedEventHandler PropertyChanged; }
(setel Window.DataContext = new MainWindowViewModel ())
sumber
boolean
nilai. Ketika Anda mengatakan itu, apakah Anda bermaksud agar saya membuatDataTrigger
untuk mencapainya?Mungkin terlambat, tapi inilah jawaban saya
foreach (Window item in Application.Current.Windows) { if (item.DataContext == this) item.Close(); }
sumber
Ini adalah sesuatu yang saya gunakan di beberapa proyek. Ini mungkin terlihat seperti retasan, tetapi berfungsi dengan baik.
public class AttachedProperties : DependencyObject //adds a bindable DialogResult to window { public static readonly DependencyProperty DialogResultProperty = DependencyProperty.RegisterAttached("DialogResult", typeof(bool?), typeof(AttachedProperties), new PropertyMetaData(default(bool?), OnDialogResultChanged)); public bool? DialogResult { get { return (bool?)GetValue(DialogResultProperty); } set { SetValue(DialogResultProperty, value); } } private static void OnDialogResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var window = d as Window; if (window == null) return; window.DialogResult = (bool?)e.NewValue; } }
Sekarang Anda dapat mengikat
DialogResult
ke VM dan menyetel nilainya untuk sebuah properti. WasiatWindow
akan ditutup, saat nilainya ditetapkan.<!-- Assuming that the VM is bound to the DataContext and the bound VM has a property DialogResult --> <Window someNs:AttachedProperties.DialogResult={Binding DialogResult} />
Ini adalah abstrak dari apa yang berjalan di lingkungan produksi kami
<Window x:Class="AC.Frontend.Controls.DialogControl.Dialog" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:DialogControl="clr-namespace:AC.Frontend.Controls.DialogControl" xmlns:hlp="clr-namespace:AC.Frontend.Helper" MinHeight="150" MinWidth="300" ResizeMode="NoResize" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterScreen" Title="{Binding Title}" hlp:AttachedProperties.DialogResult="{Binding DialogResult}" WindowStyle="ToolWindow" ShowInTaskbar="True" Language="{Binding UiCulture, Source={StaticResource Strings}}"> <!-- A lot more stuff here --> </Window>
Seperti yang Anda lihat, saya mendeklarasikan namespace
xmlns:hlp="clr-namespace:AC.Frontend.Helper"
terlebih dahulu dan kemudian mengikathlp:AttachedProperties.DialogResult="{Binding DialogResult}"
.The
AttachedProperty
terlihat seperti ini. Ini tidak sama dengan yang saya posting kemarin, tetapi IMHO seharusnya tidak berpengaruh apa pun.public class AttachedProperties { #region DialogResult public static readonly DependencyProperty DialogResultProperty = DependencyProperty.RegisterAttached("DialogResult", typeof (bool?), typeof (AttachedProperties), new PropertyMetadata(default(bool?), OnDialogResultChanged)); private static void OnDialogResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var wnd = d as Window; if (wnd == null) return; wnd.DialogResult = (bool?) e.NewValue; } public static bool? GetDialogResult(DependencyObject dp) { if (dp == null) throw new ArgumentNullException("dp"); return (bool?)dp.GetValue(DialogResultProperty); } public static void SetDialogResult(DependencyObject dp, object value) { if (dp == null) throw new ArgumentNullException("dp"); dp.SetValue(DialogResultProperty, value); } #endregion }
sumber
<Window />
elemen seperti yang saya ilustrasikan di potongan saya. Saya terlalu malas untuk menulis sisanya (deklarasi namespace dll), yang biasanya juga dideklarasikan di sana.datatrigger
dan menetapkannya ke tombol agar berfungsi? Sekali lagi maaf untuk pertanyaan nooby.DataTrigger¬ and setting value
true`?DataContext
dariDialog
. Saya berharap, bahwa VM ditetapkan sebagaiDataContext
menyediakan perintah, yang menetapkan propertiDialogResult
atau apa pun yang Anda terikattrue
ataufalse
, sehinggaDialog
ditutup.Jalan mudah
public interface IRequireViewIdentification { Guid ViewID { get; } }
Terapkan ke ViewModel
public class MyViewVM : IRequireViewIdentification { private Guid _viewId; public Guid ViewID { get { return _viewId; } } public MyViewVM() { _viewId = Guid.NewGuid(); } }
Tambahkan pembantu pengelola jendela umum
public static class WindowManager { public static void CloseWindow(Guid id) { foreach (Window window in Application.Current.Windows) { var w_id = window.DataContext as IRequireViewIdentification; if (w_id != null && w_id.ViewID.Equals(id)) { window.Close(); } } } }
Dan tutup seperti ini di viewmodel
WindowManager.CloseWindow(ViewID);
sumber
WindowManager
, yang pada gilirannya terkait erat denganView
(dalam halPresentationFramework
). Akan lebih baik jikaWindowManager
layanan diteruskan ke viewmodel melalui antarmuka. Kemudian Anda akan dapat (katakanlah) memigrasi solusi Anda ke platform yang berbeda dengan mudah.Berikut ini contoh sederhana menggunakan MVVM Light Messenger alih-alih sebuah acara. Model tampilan mengirimkan pesan tutup saat tombol diklik:
public MainViewModel() { QuitCommand = new RelayCommand(ExecuteQuitCommand); } public RelayCommand QuitCommand { get; private set; } private void ExecuteQuitCommand() { Messenger.Default.Send<CloseMessage>(new CloseMessage()); }
Kemudian itu diterima dalam kode di belakang jendela.
public Main() { InitializeComponent(); Messenger.Default.Register<CloseMessage>(this, HandleCloseMessage); } private void HandleCloseMessage(CloseMessage closeMessage) { Close(); }
sumber
Bagaimana kalau begini ?
ViewModel:
class ViewModel { public Action CloseAction { get; set; } private void Stuff() { // Do Stuff CloseAction(); // closes the window } }
Dalam ViewModel Anda, gunakan CloseAction () untuk menutup jendela seperti pada contoh di atas.
Melihat:
public View() { InitializeComponent(); ViewModel vm = new ViewModel (); // this creates an instance of the ViewModel this.DataContext = vm; // this sets the newly created ViewModel as the DataContext for the View if (vm.CloseAction == null) vm.CloseAction = new Action(() => this.Close()); }
sumber
Saya tahu ini adalah posting lama, mungkin tidak ada yang akan menggulir sejauh ini, saya tahu saya tidak melakukannya. Jadi, setelah berjam-jam mencoba berbagai hal, saya menemukan blog ini dan bung membunuhnya. Cara termudah untuk melakukan ini, mencobanya dan itu berfungsi seperti pesona.
Blog
Di ViewModel:
... public bool CanClose { get; set; } private RelayCommand closeCommand; public ICommand CloseCommand { get { if(closeCommand == null) ( closeCommand = new RelayCommand(param => Close(), param => CanClose); ) } } public void Close() { this.Close(); } ...
tambahkan properti Action ke ViewModel, tetapi tentukan dari file di belakang kode View. Ini akan membiarkan kita secara dinamis menentukan referensi pada ViewModel yang mengarah ke View.
Di ViewModel, kami hanya akan menambahkan:
public Action CloseAction { get; set; }
Dan di Tampilan, kami akan mendefinisikannya seperti ini:
public View() { InitializeComponent() // this draws the View ViewModel vm = new ViewModel(); // this creates an instance of the ViewModel this.DataContext = vm; // this sets the newly created ViewModel as the DataContext for the View if ( vm.CloseAction == null ) vm.CloseAction = new Action(() => this.Close()); }
sumber
Anda dapat membuat penangan Peristiwa baru di ViewModel seperti ini.
public event EventHandler RequestClose; protected void OnRequestClose() { if (RequestClose != null) RequestClose(this, EventArgs.Empty); }
Kemudian Tentukan RelayCommand untuk ExitCommand.
private RelayCommand _CloseCommand; public ICommand CloseCommand { get { if(this._CloseCommand==null) this._CloseCommand=new RelayCommand(CloseClick); return this._CloseCommand; } } private void CloseClick(object obj) { OnRequestClose(); }
Kemudian Di set file XAML
<Button Command="{Binding CloseCommand}" />
Setel DataContext di File xaml.cs dan Berlangganan ke acara yang kami buat.
public partial class MainWindow : Window { private ViewModel mainViewModel = null; public MainWindow() { InitializeComponent(); mainViewModel = new ViewModel(); this.DataContext = mainViewModel; mainViewModel.RequestClose += delegate(object sender, EventArgs args) { this.Close(); }; } }
sumber
Cara yang saya tawarkan adalah Menyatakan acara di ViewModel dan menggunakan campuran InvokeMethodAction seperti di bawah ini.
Contoh ViewModel
public class MainWindowViewModel : BindableBase, ICloseable { public DelegateCommand SomeCommand { get; private set; } #region ICloseable Implementation public event EventHandler CloseRequested; public void RaiseCloseNotification() { var handler = CloseRequested; if (handler != null) { handler.Invoke(this, EventArgs.Empty); } } #endregion public MainWindowViewModel() { SomeCommand = new DelegateCommand(() => { //when you decide to close window RaiseCloseNotification(); }); } }
I Antarmuka yang dapat ditutup adalah seperti di bawah ini tetapi tidak perlu melakukan tindakan ini. ICloseable akan membantu dalam membuat layanan tampilan umum, jadi jika Anda membuat tampilan dan ViewModel dengan injeksi ketergantungan maka yang dapat Anda lakukan adalah
internal interface ICloseable { event EventHandler CloseRequested; }
Penggunaan ICloseable
var viewModel = new MainWindowViewModel(); // As service is generic and don't know whether it can request close event var window = new Window() { Content = new MainView() }; var closeable = viewModel as ICloseable; if (closeable != null) { closeable.CloseRequested += (s, e) => window.Close(); }
Dan di bawah ini adalah Xaml, Anda dapat menggunakan xaml ini meskipun Anda tidak mengimplementasikan antarmuka, ini hanya membutuhkan model tampilan Anda untuk memunculkan CloseRquested.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WPFRx" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" xmlns:ViewModels="clr-namespace:WPFRx.ViewModels" x:Name="window" x:Class="WPFRx.MainWindow" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525" d:DataContext="{d:DesignInstance {x:Type ViewModels:MainWindowViewModel}}"> <i:Interaction.Triggers> <i:EventTrigger SourceObject="{Binding Mode=OneWay}" EventName="CloseRequested" > <ei:CallMethodAction TargetObject="{Binding ElementName=window}" MethodName="Close"/> </i:EventTrigger> </i:Interaction.Triggers> <Grid> <Button Content="Some Content" Command="{Binding SomeCommand}" Width="100" Height="25"/> </Grid>
sumber
Anda dapat menggunakan
Messenger
dari MVVMLight toolkit. diViewModel
kirim pesan Anda seperti ini:Messenger.Default.Send(new NotificationMessage("Close"));
lalu di kode windows Anda di belakang, setelah
InitializeComponent
, daftar untuk pesan itu seperti ini:Messenger.Default.Register<NotificationMessage>(this, m=>{ if(m.Notification == "Close") { this.Close(); } });
Anda dapat menemukan lebih banyak tentang MVVMLight toolkit di sini: MVVMLight toolkit di Codeplex
Perhatikan bahwa tidak ada aturan "tidak ada kode di belakang sama sekali" di MVVM dan Anda dapat mendaftar untuk pesan dalam tampilan di belakang kode.
sumber
Itu mudah. Anda dapat membuat kelas ViewModel Anda sendiri untuk Login - LoginViewModel. Anda bisa membuat view var dialog = new UserView (); di dalam LoginViewModel Anda. Dan Anda dapat mengatur Command LoginCommand menjadi tombol.
<Button Name="btnLogin" IsDefault="True" Content="Login" Command="{Binding LoginCommand}" />
dan
<Button Name="btnCancel" IsDefault="True" Content="Login" Command="{Binding CancelCommand}" />
Kelas ViewModel:
public class LoginViewModel { Window dialog; public bool ShowLogin() { dialog = new UserView(); dialog.DataContext = this; // set up ViewModel into View if (dialog.ShowDialog() == true) { return true; } return false; } ICommand _loginCommand public ICommand LoginCommand { get { if (_loginCommand == null) _loginCommand = new RelayCommand(param => this.Login()); return _loginCommand; } } public void CloseLoginView() { if (dialog != null) dialog.Close(); } public void Login() { if(CheckLogin()==true) { CloseLoginView(); } else { // write error message } } public bool CheckLogin() { // ... check login code return true; } }
sumber
Object reference not set to an instance of an object.
untuk metode CloseLoginView. Ada saran bagaimana mengatasi masalah itu?Ini adalah cara saya melakukannya dengan cukup sederhana:
YourWindow.xaml.cs
//In your constructor public YourWindow() { InitializeComponent(); DataContext = new YourWindowViewModel(this); }
YourWindowViewModel.cs
private YourWindow window;//so we can kill the window //In your constructor public YourWindowViewModel(YourWindow window) { this.window = window; } //to close the window public void CloseWindow() { window.Close(); }
Saya tidak melihat ada yang salah dengan jawaban yang Anda pilih, saya hanya berpikir ini mungkin cara yang lebih sederhana untuk melakukannya!
sumber
Anda dapat memperlakukan jendela sebagai layanan (mis. Layanan UI) dan mengirimkan dirinya sendiri ke viewmodel melalui antarmuka , seperti:
public interface IMainWindowAccess { void Close(bool result); } public class MainWindow : IMainWindowAccess { // (...) public void Close(bool result) { DialogResult = result; Close(); } } public class MainWindowViewModel { private IMainWindowAccess access; public MainWindowViewModel(IMainWindowAccess access) { this.access = access; } public void DoClose() { access.Close(true); } }
Solusi ini memiliki sebagian besar keuntungan dalam meneruskan tampilan itu sendiri ke model tampilan tanpa kerugian merusak MVVM, karena meskipun tampilan secara fisik diteruskan ke model tampilan, yang terakhir masih tidak tahu tentang model tampilan, ia hanya melihat beberapa
IMainWindowAccess
. Jadi misalnya jika kita ingin memigrasi solusi ini ke platform lain, itu hanya masalah penerapanIMainWindowAccess
dengan benar, katakanlah, sebuahActivity
.Saya memposting solusi di sini untuk mengusulkan pendekatan yang berbeda dari peristiwa (meskipun sebenarnya sangat mirip), karena tampaknya sedikit lebih sederhana daripada peristiwa untuk diterapkan (melampirkan / melepaskan dll.), Tetapi masih selaras dengan baik dengan pola MVVM.
sumber
Anda dapat menutup jendela saat ini hanya dengan menggunakan kode berikut:
Application.Current.Windows[0].Close();
sumber
System.Environment.Exit (0); dalam model tampilan akan bekerja.
sumber