2010-08-02 20 views
43

का उपयोग कर एक नई विंडो कैसे खोलें मैं अपने डब्ल्यूपीएफ एप्लिकेशन में एमवीवीएम लाइट टूलकिट का उपयोग कर रहा हूं। मैं जानना चाहता हूं कि मौजूदा विंडो से एक नई विंडो खोलने का सबसे अच्छा तरीका क्या है। मुझे यह MainViewModel मिला है, जो मेरे आवेदन के MainWindow के लिए ज़िम्मेदार है। अब MainView में, एक बटन क्लिक पर, मैं इसके ऊपर एक दूसरी विंडो खोलना चाहता हूं। मुझे RelayCommmandButton के Command पर मिला है। RelayCommand की विधि में, मैं एक नई विंडो वस्तु बना सकते हैं और बस Show(), कुछ इस तरह कहते हैं:एमवीवीएम लाइट टूलकिट

var view2 = new view2() 
view2.Show() 

लेकिन मुझे नहीं लगता कि ViewModel नई view2 वस्तु बनाने के लिए जिम्मेदार होना चाहिए। मैंने इस पोस्ट को WPF MVVM Get Parent from VIEW MODEL पढ़ा है जहां बग्नियन ने view1 को viewmodel1 से संदेश पास करने का सुझाव दिया है और फिर view1 को नया view2 बनाना चाहिए। लेकिन मुझे यकीन नहीं है कि संदेश को view1 पर संदेश भेजकर वास्तव में क्या मतलब है? view1 संदेश को कैसे संभालना चाहिए? इसके पीछे कोड या क्या?

सादर, नबील

+0

देखें http://stackoverflow.com/questions/16993433/mvvm-light-wpf-binding-multiple-instances-of-a-window-to-a-viewmodel/16994523#16994523 – reggaeguitar

उत्तर

50

View1 को ViewModel1 से एक संदेश पासिंग messaging capabilities in the MVVM Light Toolkit उपयोग करने के लिए इसका मतलब है।

उदाहरण के लिए, आपके ViewModel1 में ShowView2Command नामक एक कमांड हो सकता है, तो यह दृश्य प्रदर्शित करने के लिए एक संदेश भेजेगा।

public class ViewModel1 : ViewModelBase 
{ 
    public RelayCommand ShowView2Command { private set; get; } 

    public ViewModel1() : base() 
    { 
     ShowView2Command = new RelayCommand(ShowView2CommandExecute); 
    } 

    public void ShowView2CommandExecute() 
    { 
     Messenger.Default.Send(new NotificationMessage("ShowView2")); 
    } 
} 

व्यू 1 अपने कोड में संदेशों को प्राप्त करने के लिए पंजीकरण करेगा और सही संदेश प्राप्त करते समय View2 प्रदर्शित करेगा।

public partial class View1 : UserControl 
{ 
    public View1() 
    { 
     InitializeComponent(); 
     Messenger.Default.Register<NotificationMessage>(this, NotificationMessageReceived); 
    } 

    private void NotificationMessageReceived(NotificationMessage msg) 
    { 
     if (msg.Notification == "ShowView2") 
     { 
      var view2 = new view2(); 
      view2.Show(); 
     } 
    } 
} 
+0

प्रतिक्रिया मैट के लिए धन्यवाद। मैसेजिंग का उपयोग करने के अलावा एमवीवीएम में नए विचार खोलने के लिए कोई अन्य दृष्टिकोण/सर्वोत्तम प्रथाएं हैं? – nabeelfarid

+8

एक और दृष्टिकोण जिसे मैंने लोगों को देखा है, वह कक्षा की सेवा शैली है जिसका उपयोग दृश्य को खोलने के लिए किया जाता है। आपका व्यूमोडेल चाइल्डविंडो, मैसेजबॉक्स, या जो कुछ भी प्रदर्शित करने के लिए इस सेवा के इंटरफ़ेस के साथ काम करेगा। यह उन लोगों का एक पसंदीदा पसंदीदा है जो अपने दृश्य के कोड-पीछे में शून्य कोड चाहते हैं। इसके अलावा, यह थोड़ा और अधिक परीक्षण योग्य है क्योंकि आप सेवा का मज़ाक उड़ा सकते हैं और जोर दे सकते हैं कि आपके विचार को प्रदर्शित करने की विधि को बुलाया गया था। –

+2

हाँ मैंने लोगों को इसके बारे में भी बात की है। लेकिन मुझे इस दृष्टिकोण में क्या समझ में नहीं आता है कि जब आप कुछ सेवा का उपयोग कर एक दृश्य मॉडल से एक बच्चे की खिड़की खोल रहे हैं तो IDialogService.OpenChild(), आप बच्चे विंडो के मालिक को कैसे सेट करेंगे, जैसे व्यूमोडेल कॉलिंग IDialogService। OpenChild() को अपने स्वयं के विचार का संदर्भ नहीं है या नहीं? – nabeelfarid

2

जब तक मैं यहाँ बात याद आ रही है - अगर मैं पीछे कोड का उपयोग करने के लिए गए थे, तो क्यों सीधे button_click घटना को लागू नहीं और दूसरा दृश्य खोलें?

क्या Bugnion सुझाव प्रतीत हो रहा है View1 है -> बटन क्लिक -> रिले आदेश -> viewmodel1 -> संदेश -> View1 -> view1.cs -> खुला दृश्य 2.

आप testability बलिदान करने के लिए जा रहे हैं किसी भी तरह कोड-पीछे लिखकर, तो इतना लंबा रास्ता क्यों लें?

+4

लंबा मार्ग यह सुनिश्चित करेगा कि: जब आप अपने व्यूमोडेल का परीक्षण कर रहे हों, तो आप कम से कम परीक्षण कर सकते हैं कि नया संदेश खोलने के लिए एक संदेश/अनुरोध प्रसारित किया गया है। परीक्षण के दौरान इसे मॉक करने योग्य बनाने के लिए आप संदेश अनुरोध कोड को IDialogService में लपेट सकते हैं। – nabeelfarid

+2

मैं प्रेट्स से सहमत हूं, यह इतना लंबा रास्ता लेने के लिए थोड़ा पागल है। – Vincent

+1

विधि के पीछे कोड एक छोटे से ऐप के लिए ठीक है जिसमें खिड़कियों/दृश्यों की एक छोटी संख्या है। यदि आपके पास एक मुख्य विंडो है जो कुछ विवरण प्रदर्शित करने के लिए बस एक दूसरी विंडो खोलती है तो अतिरिक्त जटिलता बहुत अधिक प्रतीत होती है। यदि ऐप बड़ा हो जाता है, तो पीछे का कोड अच्छी तरह से स्केल नहीं करेगा और परीक्षण भुगतना होगा। – srock

3

आप इस तरह से कर सकते हैं जैसे आपको कुछ ईवेंट बनाने और पर रजिस्टर करने और इन्हें मॉडल में देखने के लिए कॉल करें। और उस पॉप अप विंडो को खोलें।

यह उदाहरण

public class Mainclass : MainView 
{ 
    public delegate abc RegisterPopUp(abc A); 
    public RegisterPopUp POpUpEvent ; 

    public RelayCommand ShowCommand { private set; get; } 


    public void ShowCommand() 
    { 
     ShowCommand("Your parameter"); 
    } 
} 
दृश्य MainView mn=new MainView();

यहाँ thake mn.POpUpEvent += की तरह घटना रजिस्टर टैब बटन डबल समय पर क्लिक करने के अलावा अंदर

तरह

और रजिस्टरों में विधि सही खोलने के लिए कोड पॉपअप पॉप अप खिड़की।

4

आप इस मार्ग पर क्यों जाते हैं? यह आसान है। यदि आप अपने बटन को टॉगल बटन, या हाइपरलिंक, या बटन की तरह किसी भी अन्य नियंत्रण के साथ प्रतिस्थापित करते हैं, तो आपको अपने "कोड पीछे" अपडेट करने की आवश्यकता नहीं है - यह एमवीवीएम पैटर्न का मूल सिद्धांत है। अपने नए टॉगल बटन (या जो कुछ भी) में, आप अभी भी एक ही सटीक कमांड पर बाध्यकारी समाप्त कर देते हैं।

उदाहरण के लिए, मैं एक ऐसे ग्राहक के लिए एक प्रोजेक्ट तैयार कर रहा हूं जो 2 यूआई चाहता है - प्रेजेंटेशन के मामले में कोई भी मूल रूप से अलग-अलग होने वाला है। नेविगेशन के लिए क्षैतिज टैब बनाम लंबवत RadPanelBar (सोच Accordion) बनाम। इन दोनों विचारों में एक ही दृश्य को इंगित किया जा सकता है मॉडल - जब कोई उपयोगकर्ता व्यू 1 में वर्क ऑर्डर टैब पर क्लिक करता है, तो वह उसी "वर्कऑर्डर कॉमांड" को निकाल देता है जिसे पैनल बार में वर्क ऑर्डर हेडर में निकाल दिया जाता है।

कोड-पीछे मॉडल में, आपको दो अलग-अलग ईवेंट कोड करना होगा। यहां आपको केवल एक को कोड करना होगा।

इसके अलावा, यह किसी भी लेआउट को बनाने के लिए ब्लेंड का उपयोग करके एक डिजाइनर को अनुमति देता है। जब तक उनके पास हुक (EventToCommand नियंत्रण) जगह है, तो मैं (डेवलपर के रूप में) अंतिम उत्पाद की तरह दिखने की कमी नहीं कर सकता।

लूज युग्मन अविश्वसनीय रूप से शक्तिशाली है।

2

आप जेनेरिक इंटरफेस का उपयोग कर सेवाओं में विशिष्ट विशिष्टताओं को स्पष्ट कर सकते हैं। दृश्य परत में आप इन सेवाओं के ठोस उदाहरण प्रदान कर सकते हैं और आईओसी कंटेनर और निर्भरता इंजेक्शन तकनीक का उपयोग करके दृश्य मॉडल बना सकते हैं।

अपने मामले में आप एक इंटरफ़ेस IWindowManager या ऐसा कुछ भी बना सकते हैं जिसमें आवश्यक विधि हो। इसे आपकी दृश्य परत में लगाया जा सकता है। मैंने हाल ही में एक छोटे से ब्लॉग पोस्ट को लिखा है कि दृश्य मॉडल से संवाद व्यवहार को कैसे सारणीबद्ध किया जाए। इसी प्रकार apporach नेविगेशन की तरह किसी भी यूजर इंटरफेस से संबंधित सेवा के लिए इस्तेमाल किया जा सकता है, MessageBoxes आदि

यह लिंक सहायक के लिए आप http://nileshgule.blogspot.com/2011/05/silverlight-use-dialogservice-to.html

बहुत से लोग भी है जिस पर सदस्य बन गए हैं दृश्य मॉडल से घटनाओं फायरिंग की दृष्टिकोण का उपयोग हो सकता है view.cs फ़ाइल और वहां से संदेशबॉक्स या कोई अन्य यूआई संबंधित कार्रवाई की जाती है। मैं व्यक्तिगत रूप से इंजेक्शन सेवाओं के दृष्टिकोण को पसंद करता हूं क्योंकि तब आप एक ही सेवा के कई कार्यान्वयन प्रदान कर सकते हैं। एक सरल उदाहरण यह होगा कि सिल्वरलाइट और विंडोज फोन 7 अनुप्रयोगों में नेविगेशन कैसे संभाला जाता है। आप एक ही दृश्य मॉडल का उपयोग कर सकते हैं लेकिन एप्लिकेशन प्रकार के आधार पर नेविगेशन सेवा के विभिन्न कार्यान्वयन को इंजेक्ट कर सकते हैं।

0

मुझे यह देखने का सबसे अच्छा तरीका मिल गया है, व्यूमोडेल से विंडो खोल रहा है और बंद कर रहा है। this लिंक पता चलता है,

  1. एक DialogCloser वर्ग
 
    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.Close(); 
     } 

     public static void SetDialogResult(Window target, bool? value) 
     { 
      target.SetValue(DialogResultProperty, value); 
     } 
    } 
बनाएं
  1. एक बेस ViewModel वहाँ अतिरिक्त सदस्यों के साथ GalaSoft.MvvmLight.ViewModelBase से इनहेरिट बनाएँ। एक बार पूरा हो जाने के बाद, इस व्यूमोडेल को अन्य व्यूमोडेल के लिए आधार के रूप में उपयोग करें।
 
    bool? _closeWindowFlag; 
    public bool? CloseWindowFlag 
    { 
     get { return _closeWindowFlag; } 
     set 
     { 
      _closeWindowFlag = value; 
      RaisePropertyChanged("CloseWindowFlag"); 
     } 
    } 

    public virtual void CloseWindow(bool? result = true) 
    { 
     Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, 
     new Action(() => 
     { 
      CloseWindowFlag = CloseWindowFlag == null ? true : !CloseWindowFlag; 
     })); 
    }
  1. ध्यान में रखते हुए आधार viewmodel में CloseWindowFlag संपत्ति के साथ DialogCloser.DialogResult निर्भरता संपत्ति में आबद्ध करें।

फिर आप व्यूमोडेल से विंडो को खोल/बंद/छुपा सकते हैं।

संबंधित मुद्दे