ViewModel forma necə bağlanmalıdır?

WPF və MVVM öyrənməyə çalışıram amma tələyə düşdüm. Bu sual bənzəyir, ancaq bu kimi deyil (bir-wpf-ilə-mvvm ilə dial-dialoqlar) ...

MVVM şablonunu istifadə edərək yazılmış bir giriş formum var.

Bu formanı normal məlumat bağlamalarından istifadə edərək XAML görünüşünə bağlı olan istifadəçi adı və parolu olan bir ViewModel var. Bundan əlavə, "Giriş" əmrinə malikdir, bu da "Giriş" düyməsinə, normal məlumat bağlama vasitəsi ilə forma ilə bağlıdır.

"Giriş" əmri işə salındıqda, ViewModel-də bir funksiyanı çağırır və bu şəbəkə üzərində məlumatı söndürmək və göndərmək üçün göndərir. Bu funksiya tamamlandıqda, 2 hərəkət var:

  • Giriş yanlış idi - biz yalnız MessageBox göstəririk və hər şey yaxşıdır

  • Girdi etibarlıdır, "Giriş" formasını DialogResult və doğru olaraq DialogResult olaraq geri DialogResult ...

Problem, ViewModelin faktiki görünüşü barədə heç bir şey bilməməsi, yəni görünüşü necə bağlaya bilər və ona müəyyən bir DialogResult-i qaytarması barədə xəbər verə bilər? Kodu CodeBehind'e yapışdırıb və ya Görünüşü ViewModel'e keçirə bilərəm, ancaq tamamilə MVVM nöqtəsini tamamilə məhv edəcək ...


Yeniləmə

Sonda, MVVM modelinin "təmizliyini" pozdum və Closed "Yayım" hadisə göndərdim və " Close üsulunu gətirdim. Sonra ViewModel view.Close sadəcə zəng edəcəkdir. Görünüş yalnız interfeys vasitəsi ilə tanınır və IOC konteyneri ilə əlaqələndirilir, buna görə heç bir testasiya və ya qoruma yox.

Çox aptalca görünür ki, qəbul edilən cavab -5 səs! Bir problemi həll edərkən, "təmiz" olmağımda ortaya çıxan yaxşı duyğuları yaxşı bilirəmsə də, əlbəttə ki, 200 hadisələr, əmrlər və davranışlar sadəcə "nümunələr" və "təmizlik" adı altında bir xəttli metoddan uzaqlaşdığını düşünən yeganə kişi deyiləm. ...

221
02 февр. Orion Edwards 02 fevralda təyin etdi. 2009-02-02 03:17 '09 at 3:17 pm 2009-02-02 03:17
@ 25 cavab

Mən Tejouan'ın sadə bir əlavə əmlak yazmaq üçün cavabından ilhamlandırdım. Üslub yoxdur, tetikler; Bunun əvəzinə sadəcə bunu edə bilərsiniz:

 <Window ... xmlns:xc="clr-namespace:ExCastle.Wpf" xc:DialogCloser.DialogResult="{Binding DialogResult}"> 

Bu WPF qrupunun düzgün başa düşdüyünü və DialoqResultu asılılıq əmlakını ilk növbədə hazırladığı kimi demək olar ki, təmizdir. Yalnız bool? DialogResult əmlak qoymaq bool? DialogResult ViewModel haqqında DialogResult və INotifyPropertyChanged və voilà tətbiq, sizin ViewModel xüsusiyyətini sadəcə qoyaraq pəncərəni bağlaya bilər (və onu DialogResult-a quraşdıra bilər). MVVM olması lazım olduğu kimi.

DialogCloser üçün kod:

 using System.Windows; namespace ExCastle.Wpf { public static class DialogCloser { public static readonly DependencyProperty DialogResultProperty = DependencyProperty.RegisterAttached( "DialogResult", typeof(bool?), typeof(DialogCloser), new PropertyMetadata(DialogResultChanged)); private static void DialogResultChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { var window = d as Window; if (window != null) window.DialogResult = e.NewValue as bool?; } public static void SetDialogResult(Window target, bool? value) { target.SetValue(DialogResultProperty, value); } } } 

Mən də bunu blogda yerləşdirdim.

299
25 июля '10 в 17:06 2010-07-25 17:06 Cavab Joe White tərəfindən 25 iyul 'da 17:06' də verildi 2010-07-25 17:06

Mənim fikrimcə, sual kifayət qədər yaxşıdır, çünki eyni yanaşma yalnız Giriş pəncərəsi üçün deyil, həm də onların hər biri üçün istifadə olunacaqdır. Mən bir çox cümlələ keçdim və heç kim mənə uyğun deyil. MVVM dizayn nümunəsi məqaləsindən götürülən mənzərə baxın.

Hər ViewModel sinfi bir RequestClose enventi olan WorkspaceViewModel , və type ICommand bir CloseCommand mülkiyyətindən ICommand . Mənim cari olaraq, CloseCommand əmlakının tətbiqi bir RequestClose hadisə ilə nəticələnəcəkdir.

Pəncərəni bağlamaq üçün pəncərənin OnLoaded metodu ləğv edilməlidir:

 void CustomerWindow_Loaded(object sender, RoutedEventArgs e) { CustomerViewModel customer = CustomerViewModel.GetYourCustomer(); DataContext = customer; customer.RequestClose += () => { Close(); }; } 

və ya tətbiqinizin OnStartup metodu:

  protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); MainWindow window = new MainWindow(); var viewModel = new MainWindowViewModel(); viewModel.RequestClose += window.Close; window.DataContext = viewModel; window.Show(); } 
border=0

Hesab edirəm ki, WorkspaceViewModelRequestCloseCloseCommand tətbiqi olduqca aydındır, amma ardıcıl olacağını göstərəcəyəm:

 public abstract class WorkspaceViewModel : ViewModelBase // There are nothing interest in ViewModelBase, it only implements INotifyPropertyChanged interface only { RelayCommand _closeCommand; public ICommand CloseCommand { get { if (_closeCommand == null) { _closeCommand = new RelayCommand( param => Close(), param => CanClose() ); } return _closeCommand; } } public event Action RequestClose; public virtual void Close() { if ( RequestClose!=null ) { RequestClose(); } } public virtual bool CanClose() { return true; } } 

RelayCommand mənbə kodu:

 public class RelayCommand : ICommand { #region Constructors public RelayCommand(Action<object> execute, Predicate<object> canExecute) { if (execute == null) throw new ArgumentNullException("execute"); _execute = execute; _canExecute = canExecute; } #endregion // Constructors #region ICommand Members [DebuggerStepThrough] public bool CanExecute(object parameter) { return _canExecute == null ? true : _canExecute(parameter); } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public void Execute(object parameter) { _execute(parameter); } #endregion // ICommand Members #region Fields readonly Action<object> _execute; readonly Predicate<object> _canExecute; #endregion // Fields } 

PS Bu mənbələrə görə mənə pis davranma. Mən dünən olsaydım, mənə bir neçə saat qənaət edəcəkdi ...

PPS Hər hansı bir şərh və ya təklifi gözləyirik.

62
20 янв. cavab Budda 20 yanvar verilir . 2010-01-20 14:05 '10 at 14:05 2010-01-20 14:05

Pəncərəni bağlamaq üçün əlavə tədbirlər istifadə etdim. "Mənbə" xüsusiyyətini ViewModel-ə əlavə edilmiş davranışa (mən, əslində, tetiği istifadə edirəm) bağlayın. Bu doğru olduğunda davranış pəncərəni bağlayır.

http://adammills.wordpress.com/2009/07/01/window-close-from-xaml/

16
20 июля '09 в 16:31 2009-07-20 16:31 cavab 20 iyul 2009-cu il tarixində, 16 iyul 2009-cu il tarixində, Adam Mills tərəfindən verilmişdir

Burada MVVM'nin mənfəətlərini və eksilerini mübahisə edən bir çox şərh var. Mənim üçün Nir ilə razıyam; Şablonu müvafiq olaraq istifadə etmək məsələsi və MVVM həmişə uyğun deyil. İnsanlar MVVM-lə uyğun JUST proqram inkişaf etdirmək üçün bütün vacib prinsipləri qurban vermiş görünürlər.

Lakin, hesab edirəm ki, sizin işiniz yaxşılaşdırıla bilər və bir az refactoring.

Çox hallarda rast gəldim, WPF birdən çox Window etməyinizi təmin edir. Bəlkə də DialogResult istifadə edərək, Windows əvəzinə FramePage istifadə edə bilərsiniz.

Sizin vəziyyətinizdə LoginFormViewModel , LoginCommand idarə edərdi və giriş düzgün olmadıqda, əmlakı LoginFormViewModel ə müvafiq dəyərə ( false və ya bəzi numaralandırma dəyəri, məsələn, UserAuthenticationStates.FailedAuthentication ) UserAuthenticationStates.FailedAuthentication , müvəffəqiyyətli giriş ( true və ya digər hesablama dəyəri). Daha sonra müxtəlif istifadəçi kimlik doğrulama DataTrigger cavab verən bir DataTrigger istifadə etdilər və Frame üçün Source DataTrigger dəyişdirmək üçün sadə bir Setter istifadə edə bilərsiniz.

Giriş pencerenizi bir DialogResult düşünürəm; DialogResult həqiqətən ViewModel-in mülkiyyətidir. Şübhəsiz ki, WPF ilə məhdud təcrübə, bir şey doğru deyilsə, adətən, mən WinForms-da eyni şeyi necə edəcəyimi düşünürəm.

Bu kömək edir.

14
24 марта '09 в 15:54 2009-03-24 15:54 cavab, Stimul8d tərəfindən 24 Mart 2009 , 15:54 'da verildi

Daxil etdiyiniz giriş qutusunun ilk pəncərə olduğunu nəzərə alsaq, bunu GirişViewModel sinfi daxilində sınayın:

  void OnLoginResponse(bool loginSucceded) { if (loginSucceded) { Window1 window = new Window1() { DataContext = new MainWindowViewModel() }; window.Show(); App.Current.MainWindow.Close(); App.Current.MainWindow = window; } else { LoginError = true; } } 
7
28 дек. Cavab Jim Wallace tərəfindən verilir. 2009-12-28 23:09 '10 at 11:09 PM 2009-12-28 23:09

Bununla məşğul olmağım mənim ViewModel-ə hadisə işləyicisi əlavə etməkdir. Bir istifadəçi uğurla qeydiyyata alındıqda, bir hadisə tetiklemeliyim. Mənim təqdimatımda bu hadisəyə əlavə edərdim və atəş etdiyində pəncərəni bağlayardım.

6
29 апр. Apr 29-də Billy Jacobs tərəfindən verilmiş cavab 2009-04-29 00:08 '09 da 0:08 'da 2009-04-29 00:08

Bu, sadə və təmiz bir həlldir. ViewModel'e bir hadisə əlavə edin və Pencereyi bu hadisə ilə bağlamaq üçün göstəriş edin.

Ətraflı məlumat üçün blog yazısına baxın ViewModel-dən pəncərəni bağlayın .

5
06 окт. Cavab Shimmy Oct 06 tərəfindən verilir 2011-10-06 11:14 '11 at 11:14 2011-10-06 11:14

Mən əvvəlcə nə etdiyimi, nə işlədiyini, amma çox uzun və çirkin görünür (qlobal statik hər şey yaxşıdır)

1: App.xaml.cs

 public partial class App : Application { // create a new global custom WPF Command public static readonly RoutedUICommand LoggedIn = new RoutedUICommand(); } 

2: LoginForm.xaml

 // bind the global command to a local eventhandler <CommandBinding Command="client:App.LoggedIn" Executed="OnLoggedIn" /> 

3: LoginForm.xaml.cs

 // implement the local eventhandler in codebehind private void OnLoggedIn( object sender, ExecutedRoutedEventArgs e ) { DialogResult = true; Close(); } 

4: GirişFormViewModel.cs

 // fire the global command from the viewmodel private void OnRemoteServerReturnedSuccess() { App.LoggedIn.Execute(this, null); } 

Sonra bütün bu kodları sildim və üzərinə Close metodu zəng LoginFormViewModel soruşdum. Çox yaxşı və izləmək asan oldu. IMHO, şablonların məqsədi insanlara tətbiq etdiyiniz şeyi anlamaq üçün daha asan bir yol verməkdir və bu vəziyyətdə MVVM bunu istifadə etmədiyindən daha anlamaq üçün daha çətin hala gəldi və indi bir anti-şablon halına gəldi.

4
02 февр. Orion Edwards tərəfindən verilmiş cavab 02 fevral. 2009-02-02 03:31 '09 at 3:31 am 2009-02-02 03:31

Yəqin ki, çox gec, amma eyni problemə düşdüm və mənim üçün işləyən bir həll tapdım.

Mən informasiya qutusu olmadan ərizə yaratmağı anlamıram (bəlkə bu, yalnız bir səbəb blokudur). Buna görə də MVVM ilə ölü bir sonda qaldım və dialoq göstərdim. Buna görə, bu CodeProject məqaləsinə qaçdım:

http://www.codeproject.com/KB/WPF/XAMLDialog.aspx

Bu UserControl, əsasən pəncərənin başqa bir pəncərənin vizual ağacının içərisində olmasına imkan verir (xaml-də icazə verilmir). Həmçinin, IsShowing adlı bir məntiqi DependencyProperty təqdim edir.

Bir qayda olaraq, üslubunu, əsasən, kontentin məzmunu olduqda dialoqun görüntülendiği resourcedictionary olaraq təyin edə bilərsiniz! Triggerlər vasitəsilə null:

 <Style TargetType="{x:Type d:Dialog}"> <Style.Triggers> <Trigger Property="HasContent" Value="True"> <Setter Property="Showing" Value="True" /> </Trigger> </Style.Triggers> </Style> 

Bir dialoq göstərmək istədiyiniz görünüşdə sadəcə aşağıdakıları edin:

 <d:Dialog Content="{Binding Path=DialogViewModel}"/> 

Və ViewModel-də, bütün etmək lazımdır ki, əmlakı bir dəyərə qoyur (Qeyd: ViewModel sinfi INotifyPropertyChanged-in bir şeyin baş verdiyini bilmək üçün görünüşünü dəstəkləməlidir).

beləliklə:

 DialogViewModel = new DisplayViewModel(); 

ViewModel bir görünüşü ilə əlaqələndirmək üçün, resourcedword-də bu kimi bir şeyiniz olmalıdır:

 <DataTemplate DataType="{x:Type vm:DisplayViewModel}"> <vw:DisplayView/> </DataTemplate> 

Bu halda dialoqun göstərilməsi üçün bir qatlı bir kod alacaqsınız. Aldığınız problem, informasiya qutusunu yalnız yuxarıdakı kodla bağlaya bilməyəcəksiniz. Beləliklə, DisplayViewModel devraldıran ViewModel əsas sinifində bir hadisə qoymaq və bunun əvəzinə yazmaq lazımdır

  var vm = new DisplayViewModel(); vm.RequestClose += new RequestCloseHandler(DisplayViewModel_RequestClose); DialogViewModel = vm; 

Sonra danışığın nəticəsini geri çağıraraq istifadə edə bilərsiniz.

Bu bir az çətin görünə bilər, amma təməl qoyulduqdan sonra bu olduqca sadədir. Yenə də, bu mənim tətbiqimdir, digərləri var :)

Bu kömək edir, məni xilas etdi.

3
28 мая '09 в 21:08 2009-05-28 21:08 cavab 28 may 09: 09-da Jose'a verildi

Tamam, buna görə bu sual təxminən 6 yaşındadır və mən hələ də düzgün cavabımı düşündüyümü tapa bilmərəm, buna görə mənim "2 qəpiyə" bölüşün ...

Mən, həqiqətən, bunu iki yolu var, birincisi - sadə ... ikinci sağ, buna görə sağa baxırsan, yalnız # 1 sayını atın və # 2-ə gedin

1. Tez və asan (lakin tam deyil)

Yalnız kiçik bir layihə varsa, bəzən ViewModel bir CloseWindowAction yaratmaq:

  public Action CloseWindow { get; set; } // In MyViewModel.cs 

Görünüş qutusuna və ya Baxış koduna daxil olan hər kəsə sadəcə Fəaliyyətin çağırdığı üsulunu təyin etdim:

(MVVM'nin View və ViewModel'in ayrılmasına həsr olunmuş olduğunu xatırlayın ... görünüş kodunun davranışı hələ də baxın və düzgün bir ayırma olduğu müddətdə deseninizi qırmayın)

Hər hansı bir ViewModel yeni bir pəncərə yaratsa:

 private void CreateNewView() { MyView window = new MyView(); window.DataContext = new MyViewModel { CloseWindow = window.Close, }; window.ShowDialog(); } 

Və ya əsas pəncərədə istəsəniz, sadəcə növü qurucusunun altına qoyun:

 public MyView() { InitializeComponent(); this.DataContext = new MainViewModel { CloseWindow = this.Close }; } 

bir pəncərəni bağlamaq istədiyiniz zaman, ViewModel-də bir hərəkət çağırın.


2. Doğru yol

İndi bunu doğru yol Prizma ilə (IMHO) və bütün bunları burada tapa bilərsiniz .

Etkileşim üçün bir istekte bulunabilir , yeni bir pencerede lazım olan hər hansı bir veri ilə doldurun, öğle yemeğine bağlayabilir, hatta veri geri alabilirsiniz . Bütün bunlar MVVM tərəfindən əhatə olunmuş və təsdiq edilmişdir. Pəncərənin bağlanma vəziyyətini, məsələn, istifadəçi Canceled olunduqda və ya Accepted olunduqda (OK düyməsini) əldə etdinizsə, pəncərə və məlumat lazımdırsa, bu bir az daha mürəkkəbdir və cavab 1-dir, ancaq Microsoft daha çox təklif edir və təklif olunur.

Verdiyim link bütün kod parçacıqlarını və nümunələrini ehtiva edir, buna görə heç bir kod qoymayacağam, yalnız Prism Quick Start-i yükləməyi məqaləni oxuyur və onu işə salmaq üçün çox sadə, daha ətraflı, lakin faydaları yalnız pəncərəni bağlamaqdan daha çox.

3
14 июня '15 в 2:17 2015-06-14 02:17 cavab 14 iyun 'da saat 14:17' da mFeinstein tərəfindən 2:17 ' də verildi

FYI, mən bu problemə qaçdım və hesab edirəm ki, qlobal və statik statistika ətrafında işləmir, amma bu ən yaxşı cavab olmaya bilər. Mən sizə özünüz üçün bu qərar verməyə icazə verirəm.

Mənim vəziyyətimdə, ViewModel, görünəcək pəncərənin bir nümunəsini (ViewModelMain deyə bilər) yaradır, həmçinin LoginFormViewModel (nümunə kimi yuxarıda göstərilən vəziyyəti) haqqında bilir.

Beləliklə, bir şey yaratdığım nədir ki, bir növüdür (bu, CloseWindowCommand deyirik), bir ICommand növü olan LoginFormViewModel. Sonra, çağırdığımdan əvvəl Window.ShowDialog () penceresindeyken, LoginFormViewModel penceresindeki pencereye window.Close () örneğine CloseWindowCommand özelliğini ayarladım. Sonra LoginFormViewModel içinde yapmanız gereken tek şey CloseWindowCommand.Execute () 'i kapatmaktır pəncərə

MVVM modelini pozmadan bu, bir az köhnəlmə / hackingdir, amma yaxşı işləyir.

İstədiyiniz qədər bu prosesi tənqid etməkdən həzz alırsınız, qəbul edə bilərəm :)

3
29 апр. Chris Walker tərəfindən verilmiş cavabı Apr 29 2009-04-29 21:04 '09 at 21:04 PM 2009-04-29 21:04

ViewModel'i Görünüşü qeyd edən bir hadisə təyin etməyə məcbur edə bilərsiniz. Sonra, ViewModel görünüşü bağlamaq qərarına gəldikdə, bu hadisə tetikler, bu da pencerenin bağlanmasına səbəb olur. Xüsusi bir nəticə dəyərinin geri qaytarılmasını istəyirsinizsə, bunun üçün ViewModeldə bir xüsusiyyətə sahib olursunuz.

2
24 февр. Abdulla Əl-Qawmaseh tərəfindən verilmiş cavab 24 fevral. 2011-02-24 01:00 '11 saat 01:00 'da 2011-02-24 01:00' də
 public partial class MyWindow: Window { public ApplicationSelection() { InitializeComponent(); MyViewModel viewModel = new MyViewModel(); DataContext = viewModel; viewModel.RequestClose += () => { Close(); }; } } public class MyViewModel { //...Your code... public event Action RequestClose; public virtual void Close() { if (RequestClose != null) { RequestClose(); } } public void SomeFunction() { //...Do something... Close(); } } 
1
30 авг. Əvir Twito tərəfindən verilmiş cavab 30 avqust 2016-08-30 10:14 '16 saat 10:14 'da 2016-08-30 10:14

Pəncərəni bağlamağınız lazımdırsa, onu yalnız görünüş rejimində qoyun:

ta da

  foreach (Window window in Application.Current.Windows) { if (window.DataContext == this) { window.Close(); return; } } 
0
31 янв. cavab 31 yanvar Cătălin Rădoi verilir 2014-01-31 11:02 '14 at 11:02 AM 2014-01-31 11:02

Mən aşağıdakı kimi gedərdim:

 using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; using GalaSoft.MvvmLight.Messaging; // View public partial class TestCloseWindow : Window { public TestCloseWindow() { InitializeComponent(); Messenger.Default.Register<CloseWindowMsg>(this, (msg) => Close()); } } // View Model public class MainViewModel: ViewModelBase { ICommand _closeChildWindowCommand; public ICommand CloseChildWindowCommand { get { return _closeChildWindowCommand?? (_closeChildWindowCommand = new RelayCommand(() => { Messenger.Default.Send(new CloseWindowMsg()); })); } } } public class CloseWindowMsg { } 
0
09 авг. cavabı 09 yanvarda romanoza verilir . 2014-08-09 00:34 '14 'də 0:34 2014-08-09 00:34

Niyə pəncərəni komanda parametri kimi qəbul edirsiniz?

#:

  private void Cancel( Window window ) { window.Close(); } private ICommand _cancelCommand; public ICommand CancelCommand { get { return _cancelCommand ?? ( _cancelCommand = new Command.RelayCommand<Window>( ( window ) => Cancel( window ), ( window ) => ( true ) ) ); } } 

XAML:

 <Window x:Class="WPFRunApp.MainWindow" x:Name="_runWindow" ... <Button Content="Cancel" Command="{Binding Path=CancelCommand}" CommandParameter="{Binding ElementName=_runWindow}" /> 
0
11 окт. Cavab şrifti 11 aydır . 2010-10-11 21:49 '10 at 9:49 PM 2010-10-11 21:49

Bütün cavabları oxudum, amma demək lazımdır ki, əksəriyyəti sadəcə kifayət etmir və ya daha pisdir.

DialoqServis sinfi istifadə edərək, bu informasiya qutusunu göstərmək və dialoqun nəticəsini geri qaytarmaq üçün məsuliyyət daşıyırsınız. Mən onun tətbiqi və istifadəsini nümayiş etdirən bir nümunə layihə yaratdım.

İşdə ən vacib hissələri:

 //we will call this interface in our viewmodels public interface IDialogService { bool? ShowDialog(object dialogViewModel, string caption); } //we need to display logindialog from mainwindow public class MainWindowViewModel : ViewModelBase { public string Message {get; set;} public void ShowLoginCommandExecute() { var loginViewModel = new LoginViewModel(); var dialogResult = this.DialogService.ShowDialog(loginViewModel, "Please, log in"); //after dialog is closed, do someting if (dialogResult == true  loginViewModel.IsLoginSuccessful) { this.Message = string.Format("Hello, {0}!", loginViewModel.Username); } } } public class DialogService : IDialogService { public bool? ShowDialog(object dialogViewModel, string caption) { var contentView = ViewLocator.GetView(dialogViewModel); var dlg = new DialogWindow { Title = caption }; dlg.PART_ContentControl.Content = contentView; return dlg.ShowDialog(); } } 

Daha asandır mı? EventAggregator və ya digər bənzər həllərdən daha sadə, daha oxunaqlı və daha az vacibdir, daha asan debug etmək olar?

Gördüyünüz kimi. Mənim fikrimcə, mən istifadə etdiyim modellər mənim vəzifəmdə təsvir olunan ilk ViewModel yanaşması idi: WPF-də ViewModel-dən View üçün ən yaxşı təcrübə

Əlbəttə ki, real dünyada DialogService.ShowDialog , məsələn, dialoqun özelleştirilmesi üçün daha çox variant olmalıdır. yerinə yetirmək üçün lazım olan düymələri və əmrləri. Bunu etmək üçün başqa bir yol var, amma onun görünüşü xaricindədir :)

0
14 марта '15 в 21:12 2015-03-14 21:12 Cavab Liero tərəfindən 14 Mart 2014, saat 21:12 'də verilir. 2015-03-14 21:12

Joe Whitein cavabınıAdam Mills'in cavabından bir neçə kodunu qarışdırdım, çünki istifadəçi nəzarəti programlı olaraq yaradılmış pəncərədə göstərməmişdim. Beləliklə, DialogCloser pəncərədə olmalı deyil, istifadəçi nəzarətində ola bilər.

 <UserControl ... xmlns:xw="clr-namespace:Wpf" xw:DialogCloser.DialogResult="{Binding DialogResult}"> 

Pəncərənin özünə əlavə edilmədiyi halda DialogCloser istifadəçi nəzarət pəncərəsini tapacaq.

 namespace Wpf { public static class DialogCloser { public static readonly DependencyProperty DialogResultProperty = DependencyProperty.RegisterAttached( "DialogResult", typeof(bool?), typeof(DialogCloser), new PropertyMetadata(DialogResultChanged)); private static void DialogResultChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { var window = d.GetWindow(); if (window != null) window.DialogResult = e.NewValue as bool?; } public static void SetDialogResult(DependencyObject target, bool? value) { target.SetValue(DialogResultProperty, value); } } public static class Extensions { public static Window GetWindow(this DependencyObject sender_) { Window window = sender_ as Window; return window ?? Window.GetWindow( sender_ ); } } } 
0
27 марта '14 в 19:13 2014-03-27 19:13 Cavab Anuroopa Shenoy tərəfindən verilir 27 Mart '14 19:13 2014-03-27 19:13

UserControl Dependency Property UserControl / hər hansı bir UserControl (yaxud bağlamaq istədiyiniz Window ). Aşağıdakı kimi:

  public bool CloseTrigger { get { return (bool)GetValue(CloseTriggerProperty); } set { SetValue(CloseTriggerProperty, value); } } public static readonly DependencyProperty CloseTriggerProperty = DependencyProperty.Register("CloseTrigger", typeof(bool), typeof(ControlEventBase), new PropertyMetadata(new PropertyChangedCallback(OnCloseTriggerChanged))); private static void OnCloseTriggerChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e) { //write Window Exit Code } 

ViewModel əmlakına bağlayın:

 <Window x:Class="WpfStackOverflowTempProject.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Width="525" CloseTrigger="{Binding Path=CloseWindow,Mode=TwoWay}" 

VeiwModel :

 private bool closeWindow; public bool CloseWindow { get { return closeWindow; } set { closeWindow = value; RaiseChane("CloseWindow"); } } 

İndi CloseWindow ViewModel dəyərini dəyişdirərək yaxın əməliyyatı başlayın. :)

0
08 февр. Cavab Kylo Ren 08 fevralda verilir. 2016-02-08 13:39 '16 at 1:39 pm 2016-02-08 13:39

Joe White həllini tətbiq etdim, amma təsadüfi "DialogResult" ilə problem yarandım, ancaq bir pəncərə yaradıldıqdan və informasiya qutusu kimi göstərildikdən sonra.

Я сохранял ViewModel вокруг после закрытия представления, и иногда я позже открывал новый вид с использованием той же виртуальной машины. Похоже, что закрытие нового представления перед тем, как старый View был собран с помощью мусора, вызвал DialogResultChanged , пытающийся установить свойство DialogResult в закрытом окне, что вызвало ошибку.

Моим решением было изменить DialogResultChanged , чтобы проверить свойство IsLoaded :

 private static void DialogResultChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { var window = d as Window; if (window != null  window.IsLoaded) window.DialogResult = e.NewValue as bool?; }