दिलचस्प पोस्ट
सी में अभिप्राय कार्य घोषणाएं सभी गैइट टैग कैसे सूचीबद्ध करें? JSP में इटरनेट अर्रे लिस्ट आईडी के लिए jquery चयनकर्ता विशिष्ट पाठ के साथ शुरू होता है एंड्रॉइड एप्लिकेशन में वॉल्यूम कंट्रोल पायथन पंडस की गणना और विशिष्ट परिस्थितियों का मूल्यांकन ट्रैफिकस्टैट्स एपीआई एंड्रॉइड और दैनिक डेटा उपयोग की गणना मैं एक धागा में एक स्टैक चर के संदर्भ कैसे पा सकता हूं? Matplotlib / PyPlot में फास्ट लाइव प्लॉटिंग ऐड डीबग में है, तो क्यों Gradle रिलीज़ मोड में मेरे मॉड्यूल का निर्माण करता है जांचें कि मेरा ऐप ऐपस्टोर पर एक नया संस्करण है या नहीं जावा में प्रतिलिपि कन्स्ट्रक्टर का निर्माण करना वस्तुओं के लिए array_unique? रेल पर रूबी के बराबर url सांकेतिक शब्दों में बदलना JBoss के लिए हीप डंप के लिए HeapDumpOnOutOfMemoryError पैरामीटर का उपयोग करना

एमवीवीएम के साथ डब्ल्यूपीएफ में संवाद के लिए अच्छा या बुरा अभ्यास?

हाल ही में मेरे डब्ल्यूपीएफ ऐप के लिए संवाद जोड़ने और संपादित करने की समस्या थी।

मैं अपने कोड में जो कुछ करना चाहता हूं वह ऐसा कुछ था। (मैं ज्यादातर म्यूव्यूएम के साथ व्यूमोल्डल पहला दृष्टिकोण का उपयोग करता हूं)

देखें मॉोडेल जो एक संवाद विंडो कॉल करता है:

var result = this.uiDialogService.ShowDialog("Dialogwindow Title", dialogwindowVM); // Do anything with the dialog result 

यह कैसे काम करता है?

सबसे पहले, मैंने एक संवाद सेवा बनाई:

 public interface IUIWindowDialogService { bool? ShowDialog(string title, object datacontext); } public class WpfUIWindowDialogService : IUIWindowDialogService { public bool? ShowDialog(string title, object datacontext) { var win = new WindowDialog(); win.Title = title; win.DataContext = datacontext; return win.ShowDialog(); } } 

WindowDialog एक विशेष लेकिन सरल विंडो है। मुझे अपनी सामग्री रखने की आवश्यकता है:

 <Window x:Class="WindowDialog" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Title="WindowDialog" WindowStyle="SingleBorderWindow" WindowStartupLocation="CenterOwner" SizeToContent="WidthAndHeight"> <ContentPresenter x:Name="DialogPresenter" Content="{Binding .}"> </ContentPresenter> </Window> 

dialogresult = true में संवाद के साथ एक समस्या है dialogresult = true कोड में ही प्राप्त किया जा सकता है। यही कारण है कि मैंने अपने dialogviewmodel को लागू करने के लिए एक इंटरफ़ेस बनाया है।

 public class RequestCloseDialogEventArgs : EventArgs { public bool DialogResult { get; set; } public RequestCloseDialogEventArgs(bool dialogresult) { this.DialogResult = dialogresult; } } public interface IDialogResultVMHelper { event EventHandler<RequestCloseDialogEventArgs> RequestCloseDialog; } 

जब भी मेरा dialogresult = true सोचता है कि यह समय dialogresult = true , तब इस घटना को बढ़ाएं।

 public partial class DialogWindow : Window { // Note: If the window is closed, it has no DialogResult private bool _isClosed = false; public DialogWindow() { InitializeComponent(); this.DialogPresenter.DataContextChanged += DialogPresenterDataContextChanged; this.Closed += DialogWindowClosed; } void DialogWindowClosed(object sender, EventArgs e) { this._isClosed = true; } private void DialogPresenterDataContextChanged(object sender, DependencyPropertyChangedEventArgs e) { var d = e.NewValue as IDialogResultVMHelper; if (d == null) return; d.RequestCloseDialog += new EventHandler<RequestCloseDialogEventArgs> (DialogResultTrueEvent).MakeWeak( eh => d.RequestCloseDialog -= eh;); } private void DialogResultTrueEvent(object sender, RequestCloseDialogEventArgs eventargs) { // Important: Do not set DialogResult for a closed window // GC clears windows anyways and with MakeWeak it // closes out with IDialogResultVMHelper if(_isClosed) return; this.DialogResult = eventargs.DialogResult; } 

अब कम से कम मुझे अपनी संसाधन फ़ाइल में एक DataTemplate बनाना होगा ( app.xaml या कुछ और):

 <DataTemplate DataType="{x:Type DialogViewModel:EditOrNewAuswahlItemVM}" > <DialogView:EditOrNewAuswahlItem/> </DataTemplate> 

अच्छी तरह से सभी, मैं अब अपने दृष्टिकोण से संवाद कॉल कर सकते हैं:

  var result = this.uiDialogService.ShowDialog("Dialogwindow Title", dialogwindowVM); 

अब मेरा प्रश्न, क्या आप इस समाधान के साथ कोई समस्या देखते हैं?

संपादित करें: पूर्णता के लिए IDialogResultVMHelper को लागू करना चाहिए और फिर इसे OkCommand या कुछ ऐसा ही कर सकता है:

 public class MyViewmodel : IDialogResultVMHelper { private readonly Lazy<DelegateCommand> _okCommand; public MyViewmodel() { this._okCommand = new Lazy<DelegateCommand>(() => new DelegateCommand(() => InvokeRequestCloseDialog( new RequestCloseDialogEventArgs(true)), () => YourConditionsGoesHere = true)); } public ICommand OkCommand { get { return this._okCommand.Value; } } public event EventHandler<RequestCloseDialogEventArgs> RequestCloseDialog; private void InvokeRequestCloseDialog(RequestCloseDialogEventArgs e) { var handler = RequestCloseDialog; if (handler != null) handler(this, e); } } 

2 संपादित करें: मैंने अपने इवेंटहाण्डलर कमजोर रजिस्टर करने के लिए यहां से कोड का इस्तेमाल किया है:
http://diditwith.net/2007/03/23/SolvingTheProblemWithEventsWeakEventHandlers.aspx
(वेबसाइट अब मौजूद नहीं है, वेबअर्चिव मिरर )

 public delegate void UnregisterCallback<TE>(EventHandler<TE> eventHandler) where TE : EventArgs; public interface IWeakEventHandler<TE> where TE : EventArgs { EventHandler<TE> Handler { get; } } public class WeakEventHandler<T, TE> : IWeakEventHandler<TE> where T : class where TE : EventArgs { private delegate void OpenEventHandler(T @this, object sender, TE e); private readonly WeakReference mTargetRef; private readonly OpenEventHandler mOpenHandler; private readonly EventHandler<TE> mHandler; private UnregisterCallback<TE> mUnregister; public WeakEventHandler(EventHandler<TE> eventHandler, UnregisterCallback<TE> unregister) { mTargetRef = new WeakReference(eventHandler.Target); mOpenHandler = (OpenEventHandler)Delegate.CreateDelegate( typeof(OpenEventHandler),null, eventHandler.Method); mHandler = Invoke; mUnregister = unregister; } public void Invoke(object sender, TE e) { T target = (T)mTargetRef.Target; if (target != null) mOpenHandler.Invoke(target, sender, e); else if (mUnregister != null) { mUnregister(mHandler); mUnregister = null; } } public EventHandler<TE> Handler { get { return mHandler; } } public static implicit operator EventHandler<TE>(WeakEventHandler<T, TE> weh) { return weh.mHandler; } } public static class EventHandlerUtils { public static EventHandler<TE> MakeWeak<TE>(this EventHandler<TE> eventHandler, UnregisterCallback<TE> unregister) where TE : EventArgs { if (eventHandler == null) throw new ArgumentNullException("eventHandler"); if (eventHandler.Method.IsStatic || eventHandler.Target == null) throw new ArgumentException("Only instance methods are supported.", "eventHandler"); var wehType = typeof(WeakEventHandler<,>).MakeGenericType( eventHandler.Method.DeclaringType, typeof(TE)); var wehConstructor = wehType.GetConstructor(new Type[] { typeof(EventHandler<TE>), typeof(UnregisterCallback<TE>) }); IWeakEventHandler<TE> weh = (IWeakEventHandler<TE>)wehConstructor.Invoke( new object[] { eventHandler, unregister }); return weh.Handler; } } 

Solutions Collecting From Web of "एमवीवीएम के साथ डब्ल्यूपीएफ में संवाद के लिए अच्छा या बुरा अभ्यास?"

यह एक अच्छा तरीका है और मैंने इसी तरह के लोगों को अतीत में इस्तेमाल किया था। इसका लाभ उठाएं!

एक छोटी सी बात मैं निश्चित रूप से करता हूं, जब आपको डायलॉग परिणाम में "झूठे" सेट करने की आवश्यकता होती है तो घटना को बुलियन प्राप्त होता है।

 event EventHandler<RequestCloseEventArgs> RequestCloseDialog; 

और EventArgs वर्ग:

 public class RequestCloseEventArgs : EventArgs { public RequestCloseEventArgs(bool dialogResult) { this.DialogResult = dialogResult; } public bool DialogResult { get; private set; } } 

मैं कई महीनों के लिए अब लगभग समान दृष्टिकोण का उपयोग कर रहा हूं, और मैं इसके साथ बहुत खुश हूं (यानी मैंने अभी तक इसे फिर से लिखने की इच्छा नहीं महसूस की है) …

मेरे क्रियान्वयन में, मैं एक IDialogViewModel उपयोग करता IDialogViewModel जो शीर्षक, जैसे स्टैंडबाय बटन दिखाता है (सभी संवादों में एक सुसंगत apparence के लिए), एक requestclose घटना, और खिड़की को नियंत्रित करने में सक्षम होने के लिए कुछ अन्य चीजें आकार और व्यवहार

यदि आप संवाद विंडो के बारे में बात कर रहे हैं और न केवल पॉप-अप संदेश बॉक्स के बारे में, कृपया नीचे दिए गए मेरा दृष्टिकोण पर विचार करें। प्रमुख बिंदु हैं:

  1. मैं Module Controller के लिए प्रत्येक ViewModel (आप इंजेक्शन का उपयोग कर सकते हैं) में एक संदर्भ पास करते हैं।
  2. उस Module Controller में संवाद विंडो बनाने के लिए सार्वजनिक / आंतरिक तरीके हैं (न ही कोई परिणाम लौटाए बिना)। इसलिए मैं ViewModel में एक संवाद विंडो खोलने के लिए लिखूंगा: controller.OpenDialogEntity(bla, bla...) ओपन ViewModel controller.OpenDialogEntity(bla, bla...)
  3. कमज़ोर घटनाओं के माध्यम से प्रत्येक संवाद विंडो इसके परिणाम (जैसे ओके , सहेजें , रद्द करें आदि) के बारे में सूचित करता है। यदि आप PRISM का उपयोग करते हैं, तो इस EventAggregator का उपयोग करके सूचनाएं प्रकाशित करना आसान है।
  4. वार्ता के परिणामों को संभालने के लिए, मैं अधिसूचनाओं की सदस्यता का उपयोग कर रहा हूं (फिर से कमजोर घटनाएं और इवेंटएजेगेटर , प्रिज्म के मामले में) ऐसी सूचनाओं पर निर्भरता को कम करने के लिए, मानक सूचनाओं के साथ स्वतंत्र कक्षाओं का उपयोग करें

पेशेवरों:

  • कम कोड इंटरफेस का उपयोग करने पर मुझे कोई दिक्कत नहीं है, लेकिन मैंने बहुत सारे प्रोजेक्ट देखे हैं, जहां इंटरफेस और एब्स्ट्रैक्शन परतों का इस्तेमाल करने की अधिकता मदद की तुलना में अधिक परेशानी का कारण है।
  • Module Controller माध्यम से संवाद विंडो खोलें मजबूत संदर्भों से बचने का एक आसान तरीका है और फिर भी परीक्षण के लिए नकली-अप का उपयोग करने की अनुमति देता है।
  • कमजोर घटनाओं के माध्यम से अधिसूचना संभावित स्मृति लीक की संख्या को कम करता है।

विपक्ष:

  • हेन्डलर में दूसरों से आवश्यक नोटिफिकेशन को अलग करना आसान नहीं है दो समाधान:
    • वार्तालाप विंडो खोलने के लिए एक अद्वितीय टोकन भेजें और सदस्यता में उस टोकन की जांच करें
    • जेनेरिक अधिसूचना कक्षाओं का उपयोग करें <T> जहां T इकाइयों की गणना है (या सादगी के लिए यह देखेंमोडेल का प्रकार हो सकता है)
  • प्रोजेक्ट को डुप्लिकेट करने के लिए अधिसूचना कक्षाओं का उपयोग करने के बारे में एक समझौता होना चाहिए।
  • अत्यधिक बड़ी परियोजनाओं के लिए Module Controller को विंडोज़ बनाने के तरीकों से अभिभूत हो सकता है इस मामले में इसे कई मॉड्यूलों में विभाजित करना बेहतर होगा।

पीएस मैं इस दृष्टिकोण का उपयोग अब काफी समय तक कर रहा हूं और टिप्पणियों में अपनी योग्यता की रक्षा के लिए तैयार हूं और यदि आवश्यक हो तो कुछ उदाहरण प्रदान करें।