एमवीवीएम के साथ डब्ल्यूपीएफ में संवाद संभालना


235

WPF के लिए MVVM पैटर्न में, संवादों को संभालना अधिक जटिल परिचालनों में से एक है। जैसा कि आपके दृश्य मॉडल को दृश्य के बारे में कुछ भी नहीं पता है, संवाद संचार दिलचस्प हो सकता है। मैं इसे उजागर कर सकता हूं ICommandकि जब दृश्य इसे लागू करता है, तो एक संवाद दिखाई दे सकता है।

क्या किसी को संवादों से परिणाम को संभालने का एक अच्छा तरीका पता है? मैं विंडोज़ संवादों के बारे में बोल रहा हूँ जैसे MessageBox

जिन तरीकों से हमने यह किया था, उनमें से एक व्यूमोडल पर एक घटना थी जिसे देखने के लिए एक संवाद की आवश्यकता होती है।

public event EventHandler<MyDeleteArgs> RequiresDeleteDialog;

यह ठीक है, लेकिन इसका मतलब है कि दृश्य के लिए कोड की आवश्यकता होती है, जो कुछ ऐसा है जिससे मैं दूर रहना चाहता हूं।


दृश्य में सहायक वस्तु से क्यों नहीं बंधे?
पॉल विलियम्स

1
पक्का नहीं आपका क्या मतलब है।
रे बोयसेन

1
यदि मैं इस प्रश्न को समझता हूं, तो आप VM को डायलॉग पॉप अप नहीं करना चाहते हैं, और आप व्यू में कोड-पीछे नहीं चाहते हैं। इसके अलावा ऐसा लगता है कि आप ईवेंट के लिए कमांड पसंद करते हैं। मैं इन सभी से सहमत हूं, इसलिए मैं व्यू में एक सहायक वर्ग का उपयोग करता हूं जो संवाद को संभालने के लिए एक कमांड को उजागर करता है। मैंने इस प्रश्न का उत्तर एक और सूत्र पर दिया है: stackoverflow.com/a/23303267/420400 । हालाँकि, अंतिम वाक्य ऐसा लगता है जैसे आप किसी भी कोड को व्यू में कहीं भी नहीं चाहते हैं । मैं उस चिंता को समझता हूं लेकिन प्रश्न में कोड केवल एक सशर्त है, और इसे बदलने की संभावना नहीं है।
पॉल विलियम्स

4
संवाद बॉक्स के निर्माण के पीछे के तर्क के लिए Thje व्यू मॉडल को हमेशा जिम्मेदार होना चाहिए, यही कारण है कि इसके अस्तित्व में आने का पूरा कारण है। यह कहा कि यह (और नहीं करना चाहिए) ही दृश्य बनाने की भारी उठाने करना चाहिए। मैंने इस विषय पर codeproject.com/Articles/820324/… पर एक लेख लिखा था, जहां मैं बताता हूं कि डायलॉग बॉक्स के पूरे जीवन चक्र को नियमित WPF डेटा बाइंडिंग और MVVM पैटर्न को तोड़े बिना प्रबंधित किया जा सकता है।
मार्क फेल्डमैन

जवाबों:


131

मेरा सुझाव है कि 1990 के मौडल संवादों को आगे बढ़ाएं और इसके बजाय वीएम में बूलियन बैक से जुड़ी दृश्यता के साथ एक ओवरले (कैनवास + पूर्ण स्थिति) के रूप में एक नियंत्रण को लागू करें। अजाक्स प्रकार नियंत्रण के करीब।

यह बहुत उपयोगी है:

<BooleanToVisibilityConverter x:Key="booltoVis" />

जैसे की:

<my:ErrorControl Visibility="{Binding Path=ThereWasAnError, Mode=TwoWay, Converter={StaticResource booltoVis}, UpdateSourceTrigger=PropertyChanged}"/>

यहां बताया गया है कि मैंने एक उपयोगकर्ता नियंत्रण के रूप में कैसे लागू किया है। 'X' पर क्लिक करने से उपयोगकर्ता के नियंत्रण के पीछे कोड की एक पंक्ति में नियंत्रण बंद हो जाता है। (चूंकि मेरे पास एक d .exe और ViewModels में एक dll में मेरे दृश्य हैं, इसलिए मुझे यूआई में हेरफेर करने वाले कोड के बारे में बुरा नहीं लगता है।)

Wpf संवाद


20
हाँ, मुझे यह विचार भी पसंद है, लेकिन इस नियंत्रण के कुछ उदाहरणों को कैसे दिखाना है, और इसके बारे में संवाद परिणाम प्राप्त करना चाहते हैं, खासकर सिल्वरलाइट में MVVM परिदृश्य में।
Roboblob

16
आप इस संवाद उपरिशायी के तहत नियंत्रण के साथ बातचीत से उपयोगकर्ता को कैसे रोक सकते हैं?
एंड्रयू गैरीसन

16
इस दृष्टिकोण के साथ समस्या यह है कि आप पहले से एक दूसरा मोडल संवाद नहीं खोल सकते हैं, कम से कम ओवरले सिस्टम के लिए कुछ भारी संशोधनों के बिना नहीं ...
थॉमस लेवेस्क

6
इस दृष्टिकोण के साथ एक और समस्या यह है कि "संवाद" को स्थानांतरित नहीं किया जा सकता है। हमारे अनुप्रयोगों में, हमारे पास एक जंगम संवाद होना चाहिए ताकि उपयोगकर्ता देख सके कि इसके पीछे क्या है।
JAB

12
यह दृष्टिकोण मुझे भयानक लगता है। मैं क्या खो रहा हूँ? यह एक वास्तविक संवाद बॉक्स से बेहतर कैसे है?
जोनाथन वुड

51

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

आपको Google WPF शिष्य समूह की जाँच करनी चाहिए, और बस मध्यस्थ की खोज करनी चाहिए। जवाब से आप बहुत खुश होंगे ...

आप इसके साथ शुरू कर सकते हैं:

http://joshsmithonwpf.wordpress.com/2009/04/06/a-mediator-prototype-for-wpf-apps/

का आनंद लें !

संपादित करें: आप इस समस्या का उत्तर MVVM लाइट टूलकिट के साथ देख सकते हैं:

http://mvvmlight.codeplex.com/Thread/View.aspx?ThreadId=209338


2
मार्लोन ग्रीच ने अभी-अभी मध्यस्थ का बिल्कुल नया कार्यान्वयन पोस्ट किया है: marlongrech.wordpress.com/2009/04/16/…
Roubachof

21
बस एक टिप्पणी: WPF चेले द्वारा मध्यस्थ पैटर्न पेश नहीं किया गया था, यह एक शास्त्रीय GoF पैटर्न है ... ( dofactory.com/Patterns/PatternMediator.aspx )। अच्छा जवाब अन्यथा;)
थॉमस लेवेस्क

10
भगवान, कृपया एक मध्यस्थ या एक दूत का उपयोग न करें। दर्जनों संदेशों के साथ इस तरह का कोड चारों ओर उड़ना बहुत मुश्किल हो जाता है जब तक कि आप किसी तरह से अपने पूरे कोडबेस में उन सभी बिंदुओं को याद नहीं कर सकते हैं जो हर घटना को सब्सक्राइब और संभालते हैं। यह नए देवों के लिए एक बुरा सपना बन जाता है। वास्तव में, मैं संपूर्ण MvvMLight लाइब्रेरी को अपने व्यापक और अनावश्यक उपयोग के लिए असिंक्रोनस मैसेजिंग के लिए एक व्यापक विरोधी पैटर्न मानता हूं। समाधान सरल है: अपने डिजाइन का एक अलग संवाद सेवा (यानी, IDialogService) को कॉल करें। इंटरफ़ेस में कॉलबैक के लिए तरीके और घटनाएं हैं।
क्रिस बॉर्डमैन

34

एक अच्छा MVVM संवाद चाहिए:

  1. केवल एक्सएएमएल के साथ घोषित किया जाए।
  2. डेटाबाइंडिंग से इसका व्यवहार प्राप्त करें।

दुर्भाग्य से, WPF इन सुविधाओं को प्रदान नहीं करता है। डायलॉग दिखाने के लिए कोड-पीछे कॉल की आवश्यकता होती है ShowDialog()। विंडो क्लास, जो संवादों का समर्थन करती है, को XAML में घोषित नहीं किया जा सकता है, इसलिए इसे आसानी से डेटाबाउंड नहीं किया जा सकता है DataContext

इसे हल करने के लिए, मैंने एक XAML ठूंठ नियंत्रण लिखा जो तार्किक पेड़ में बैठता है और एक को डेटाबाइंडिंग और डायल को Windowदिखाने और छुपाने के लिए हैंडल करता है। आप इसे यहां देख सकते हैं: http://www.codeproject.com/KB/WPF/XAMLDialog.aspx

यह वास्तव में उपयोग करने के लिए है और आपके ViewModel में किसी भी अजीब बदलाव की आवश्यकता नहीं है और इसे घटनाओं या संदेशों की आवश्यकता नहीं है। मूल कॉल इस तरह दिखता है:

<dialog:Dialog Content="{Binding Path=DialogViewModel}" Showing="True" />

आप शायद एक शैली जोड़ना चाहते हैं जो सेट करता है Showing। मैं इसे अपने लेख में समझाता हूं। मैं आशान्वित हूं कि इससे आपको सहायता मिलेगी।


2
MVVM में डायलॉग विंडो दिखाने की समस्या के लिए यह वास्तव में एक दिलचस्प तरीका है।
दशहरा

2
"Showing a dialog requires a code-behind"mmm को आप ViewModel
Brock Hensley

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

25

मैं MVVM के साथ संवाद के लिए इस दृष्टिकोण का उपयोग करता हूं ।

अब मुझे बस इतना करना है कि मेरे विचार मॉडल से निम्नलिखित कॉल करें।

var result = this.uiDialogService.ShowDialog("Dialogwindow title goes here", dialogwindowVM);

किस पुस्तकालय से uiDialogService आता है?
21

1
कोई पुस्तकालय नहीं। बस एक छोटा सा इंटरफ़ेस और कार्यान्वयन है: stackoverflow.com/questions/3801681/… । निष्पक्ष होने के लिए यह मेरी जरूरतों के लिए कुछ और अधिक भार है :) (ऊंचाई, चौड़ाई, संपत्ति और इतने पर)
अंधा

16

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

MVVM और सिल्वरलाइट 4 के साथ मोडल संवाद यहाँ पूर्ण सिल्वरलाइट 4 समाधान देखें


@Elad Katz के दृष्टिकोण की तरह, आपके उत्तर में लिंक की गई सामग्री का अभाव है - कृपया अपने उत्तर को इसमें सम्मिलित करके सुधारें, क्योंकि यहाँ SO पर एक अच्छा उत्तर माना जाता है। बहरहाल, आपके योगदान के लिए धन्यवाद! :)
योदा

6

मैं वास्तव में इस अवधारणा के साथ थोड़ी देर के लिए संघर्ष कर रहा था जब सीखने (अभी भी सीख रहा है) एमवीवीएम। मैंने जो निर्णय लिया, और जो मुझे लगता है कि अन्य लोग पहले से ही तय कर चुके हैं, लेकिन जो मेरे लिए स्पष्ट नहीं था वह यह है:

मेरा मूल विचार यह था कि एक ViewModel को सीधे संवाद बॉक्स को कॉल करने की अनुमति नहीं दी जानी चाहिए क्योंकि इसमें कोई व्यवसाय नहीं है जो यह तय करता है कि एक संवाद कैसे प्रकट होना चाहिए। इसके बारे में मैं सोचने लगा कि मैं कैसे संदेश को पास कर सकता हूं जैसे कि मैं MVP (यानी View.ShowSaveFileDialog ()) में होगा। हालांकि, मुझे लगता है कि यह गलत तरीका है।

सीधे किसी डायलॉग को कॉल करना ViewModel के लिए ठीक है। हालाँकि, जब आप एक ViewModel का परीक्षण कर रहे हैं, तो इसका मतलब है कि संवाद या तो आपके परीक्षण के दौरान पॉप अप होगा, या सभी को एक साथ विफल कर देगा (कभी भी वास्तव में यह कोशिश नहीं की गई है)।

इसलिए, परीक्षण के दौरान "परीक्षण" संस्करण का उपयोग करना है। इसका मतलब है कि आपके पास कभी भी होने वाले संवाद के लिए, आपको एक इंटरफ़ेस बनाना होगा और या तो डायलॉग रिस्पांस को मॉक करना होगा या एक टेस्टिंग मॉक बनाना होगा जिसमें डिफ़ॉल्ट व्यवहार होगा।

आपको पहले से ही किसी प्रकार के सेवा लोकेटर या IoC का उपयोग करना चाहिए जिसे आप संदर्भ के आधार पर आपको सही संस्करण प्रदान करने के लिए कॉन्फ़िगर कर सकते हैं।

इस दृष्टिकोण का उपयोग करते हुए, आपका ViewModel अभी भी परीक्षण योग्य है और इस बात पर निर्भर करता है कि आप अपने संवादों का मजाक कैसे उड़ाते हैं, आप व्यवहार को नियंत्रित कर सकते हैं।

उम्मीद है की यह मदद करेगा।


6

ऐसा करने के दो अच्छे तरीके हैं, 1) एक डायलॉग सर्विस (आसान, साफ) और 2) व्यू असिस्टेड। सहायता प्राप्त दृश्य कुछ साफ-सुथरी विशेषताएं प्रदान करता है, लेकिन आमतौर पर इसके लायक नहीं है।

डायल सेवा

क) निर्माता या कुछ निर्भरता कंटेनर के माध्यम से एक संवाद सेवा इंटरफ़ेस:

interface IDialogService { Task ShowDialogAsync(DialogViewModel dlgVm); }

ख) IDialogService के आपके कार्यान्वयन को एक विंडो खोलनी चाहिए (या सक्रिय विंडो में कुछ नियंत्रण इंजेक्ट करें), दिए गए dlgVm प्रकार (कंटेनर पंजीकरण या सम्मेलन का उपयोग करें या एक प्रकार का DataTemplates के साथ एक ContentPresenter) के नाम के अनुरूप दृश्य बनाएं। ShowDialogAsync एक TaskCompletionSource बनाना चाहिए और इसे वापस करना चाहिए। जब आप बंद करना चाहते हैं, तो DialogViewModel वर्ग को एक ऐसी घटना की आवश्यकता होती है, जिसे आप व्युत्पन्न वर्ग में शामिल कर सकते हैं और संवाद दृश्य में वास्तव में बंद / छुपाने और कार्य को पूरा करने के लिए कार्य देखें।

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

वर्गीकृत देखें

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

a) एक कस्टम पेलोड (एक DialogViewModel व्युत्पन्न वर्ग) के साथ एक OpenXXXXXDialogEvent बनाएँ।

ख) अपने ऑनडॉटकॉन्टेक्स्टडेंज इवेंट में घटना के लिए सदस्यता लें। यदि पुराने मान! = अशक्त और विंडो के अनलोड किए गए ईवेंट में छिपाना और बंद करना सुनिश्चित करें।

c) जब ईवेंट भड़कता है, तो दृश्य को अपना दृश्य खोलें, जो आपके पेज पर एक संसाधन में हो सकता है, या आप इसे कहीं और कन्वेंशन द्वारा पता लगा सकते हैं (जैसे डायलॉग सेवा दृष्टिकोण में)।

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

यह संवादों को उस जगह के करीब होने की अनुमति देता है, जिसका वे वास्तव में उपयोग करते हैं, वर्तमान गतिविधि से संबंधित एप्लिकेशन के हिस्से को ही मंद कर देते हैं, और उपयोगकर्ता को एप्लिकेशन के भीतर चारों ओर ले जाने देते हैं, बिना संवादों को मैन्युअल रूप से दूर करने के लिए, यहां तक ​​कि कई अर्ध भी हैं- मोडल संवाद विभिन्न टैब या उप-दृश्य पर खुलते हैं।


एक संवाद सेवा बहुत आसान है, निश्चित रूप से, और मैं आमतौर पर क्या करता हूं। यह पैरेंट व्यू मॉडल से व्यू के डायलॉग को बंद करना भी आसान बनाता है, जो कि पेरेंट व्यू मॉडल को बंद करने या रद्द करने के दौरान आवश्यक है।
क्रिस बॉर्डमैन

4

एक फ्रीज़ेबल कमांड का उपयोग करें

<Grid>
        <Grid.DataContext>
            <WpfApplication1:ViewModel />
        </Grid.DataContext>


        <Button Content="Text">
            <Button.Command>
                <WpfApplication1:MessageBoxCommand YesCommand="{Binding MyViewModelCommand}" />
            </Button.Command>
        </Button>

</Grid>
public class MessageBoxCommand : Freezable, ICommand
{
    public static readonly DependencyProperty YesCommandProperty = DependencyProperty.Register(
        "YesCommand",
        typeof (ICommand),
        typeof (MessageBoxCommand),
        new FrameworkPropertyMetadata(null)
        );


    public static readonly DependencyProperty OKCommandProperty = DependencyProperty.Register(
        "OKCommand",
        typeof (ICommand),
        typeof (MessageBoxCommand),
        new FrameworkPropertyMetadata(null)
        );


    public static readonly DependencyProperty CancelCommandProperty = DependencyProperty.Register(
        "CancelCommand",
        typeof (ICommand),
        typeof (MessageBoxCommand),
        new FrameworkPropertyMetadata(null)
        );


    public static readonly DependencyProperty NoCommandProperty = DependencyProperty.Register(
        "NoCommand",
        typeof (ICommand),
        typeof (MessageBoxCommand),
        new FrameworkPropertyMetadata(null)
        );


    public static readonly DependencyProperty MessageProperty = DependencyProperty.Register(
        "Message",
        typeof (string),
        typeof (MessageBoxCommand),
        new FrameworkPropertyMetadata("")
        );

    public static readonly DependencyProperty MessageBoxButtonsProperty = DependencyProperty.Register(
        "MessageBoxButtons",
        typeof(MessageBoxButton),
        typeof(MessageBoxCommand),
        new FrameworkPropertyMetadata(MessageBoxButton.OKCancel)
        );

    public ICommand YesCommand
    {
        get { return (ICommand) GetValue(YesCommandProperty); }
        set { SetValue(YesCommandProperty, value); }
    }

    public ICommand OKCommand
    {
        get { return (ICommand) GetValue(OKCommandProperty); }
        set { SetValue(OKCommandProperty, value); }
    }

    public ICommand CancelCommand
    {
        get { return (ICommand) GetValue(CancelCommandProperty); }
        set { SetValue(CancelCommandProperty, value); }
    }

    public ICommand NoCommand
    {
        get { return (ICommand) GetValue(NoCommandProperty); }
        set { SetValue(NoCommandProperty, value); }
    }

    public MessageBoxButton MessageBoxButtons
    {
        get { return (MessageBoxButton)GetValue(MessageBoxButtonsProperty); }
        set { SetValue(MessageBoxButtonsProperty, value); }
    }

    public string Message
    {
        get { return (string) GetValue(MessageProperty); }
        set { SetValue(MessageProperty, value); }
    }

    public void Execute(object parameter)
    {
        var messageBoxResult = MessageBox.Show(Message);
        switch (messageBoxResult)
        {
            case MessageBoxResult.OK:
                OKCommand.Execute(null);
                break;
            case MessageBoxResult.Yes:
                YesCommand.Execute(null);
                break;
            case MessageBoxResult.No:
                NoCommand.Execute(null);
                break;
            case MessageBoxResult.Cancel:
                if (CancelCommand != null) CancelCommand.Execute(null); //Cancel usually means do nothing ,so can be null
                break;

        }
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;


    protected override Freezable CreateInstanceCore()
    {
        throw new NotImplementedException();
    }
}

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

3

मुझे लगता है कि किसी संवाद को संभालना दृश्य की जिम्मेदारी होनी चाहिए, और उस समर्थन के लिए दृश्य के पास कोड होना चाहिए।

यदि आप ViewModel को बदलते हैं - संवादों को संभालने के लिए सहभागिता देखें तो ViewModel उस कार्यान्वयन पर निर्भर है। इस समस्या से निपटने का सबसे सरल तरीका यह है कि कार्य करने के लिए व्यू को जिम्मेदार बनाएं। अगर इसका मतलब है कि संवाद दिखाना तो ठीक है, लेकिन स्टेटस बार आदि में एक स्टेटस मैसेज भी हो सकता है।

मेरा कहना है कि MVVM पैटर्न का पूरा बिंदु GUI से व्यावसायिक तर्क को अलग करना है, इसलिए आपको GUI तर्क (संवाद प्रदर्शित करने के लिए) को व्यावसायिक परत (ViewModel) में नहीं मिलाना चाहिए।


2
VM डायलॉग को कभी भी हैंडल नहीं करेगा, मेरे उदाहरण में यह एक ऐसी घटना होगी जिसमें डायलॉग को आग लगाने और EventArgs के किसी न किसी रूप में जानकारी वापस करने की आवश्यकता होगी। यदि दृश्य जिम्मेदार है, तो यह VM को वापस जानकारी कैसे देता है?
रे बोयसेन

कहें कि VM को कुछ हटाने की आवश्यकता है। वीएम व्यू डिलीट पर एक विधि कहता है जो एक बूलियन देता है। इसके बाद व्यू सीधे आइटम को हटा सकता है और सही लौटा सकता है, या एक पुष्टि डायलॉग दिखा सकता है और उपयोगकर्ताओं के उत्तर के आधार पर सही / गलत लौटा सकता है।
कैमरन मैकफारलैंड

VM डायलॉग के बारे में कुछ नहीं जानता है, लेकिन केवल कुछ को हटाने के लिए दृश्य को कहा है, जिसे देखने या तो पुष्टि की गई या नकार दी गई।
कैमरन मैकफारलैंड

मैंने हमेशा सोचा था कि एमवीवीएम का मुद्दा मॉडल था: व्यापार तर्क, ViewModel: GUI तर्क और दृश्य: कोई तर्क नहीं। जो किसी तरह आपके अंतिम पैराग्राफ द्वारा विरोधाभास है। कृपया समझाएँ!
डेविड श्मिट

2
पहले यह निर्धारित करना होगा कि प्री-डिलीट कन्फर्मेशन के लिए पूछना बिजनेस लॉजिक है या लॉजिक। यदि यह व्यावसायिक तर्क है, तो मॉडल में DeleteFile पद्धति को ऐसा नहीं करना चाहिए, बल्कि पुष्टिकरण प्रश्न ऑब्जेक्ट को वापस करना चाहिए। इसमें प्रतिनिधि के लिए एक संदर्भ शामिल होगा जो वास्तविक विलोपन करता है। यदि यह व्यावसायिक तर्क नहीं है, तो VM को ICFANDC सदस्य के साथ DeleteFileCommand में प्रश्न का एक VM बनाना चाहिए। एक के लिए हाँ और एक के लिए नहीं। दोनों विचारों के लिए तर्क हैं, और आरएल में अधिकांश उपयोग संभवतः दोनों का सामना करेंगे।
गुज़रे

3

एक दिलचस्प विकल्प नियंत्रक का उपयोग करना है जो विचार (संवाद) दिखाने के लिए जिम्मेदार हैं।

यह कार्य WPF Application Framework (WAF) द्वारा कैसे दिखाया जाता है ।


3

क्यों न केवल वीएम में एक घटना को बढ़ाएं और दृश्य में घटना की सदस्यता लें? यह एप्लिकेशन लॉजिक और दृश्य को अलग रखेगा और फिर भी आपको संवादों के लिए चाइल्ड विंडो का उपयोग करने की अनुमति देगा।


3

मैंने एक व्यवहार लागू किया है जो ViewModel के एक संदेश को सुनता है। यह लॉरेंट बगनियन समाधान पर आधारित है, लेकिन चूंकि यह पीछे कोड का उपयोग नहीं करता है और अधिक पुन: प्रयोज्य है, मुझे लगता है कि यह अधिक सुरुचिपूर्ण है।

WPF कैसे करें जैसे कि MVVM बॉक्स से बाहर समर्थित है


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

2
@ कोड पूरा कोड काफी लंबा है, और इसीलिए मैं इसे लिंक करना चाहूंगा। मैंने परिवर्तनों को प्रतिबिंबित करने और एक लिंक को इंगित करने के लिए अपने उत्तर को संपादित किया है जो टूटा नहीं है
एलाड काटज़

सुधार के लिए धन्यवाद। फिर भी, कोड 3 पूर्ण-पृष्ठ स्क्रॉल को एसओ पर लंबे समय तक लिंक देने से बेहतर है कि किसी दिन ऑफ़लाइन हो। जटिल विषयों के लिए अच्छे लेख हमेशा बहुत लंबे होते हैं - और मुझे एक नया टैब खोलने, उसमें स्विच करने और वहाँ स्क्रॉल करने में कोई लाभ नहीं दिखाई देता है, उसी पृष्ठ / टैब पर स्क्रॉल करने से पहले जो मैं उस पर था। ;)
योडा

@EladKatz मैंने देखा है कि आपने अपने द्वारा दिए गए लिंक में अपने कुछ WPF कार्यान्वयन को साझा किया है। क्या आपके पास ViewModel से एक नई विंडो खोलने का कोई समाधान है? मूल रूप से मेरे दो रूप हैं और प्रत्येक के पास एक ViewModel है। एक उपयोगकर्ता एक बटन पर क्लिक करता है दूसरा रूप पॉप अप करता है और viewmodel1 viewmodel2 पर अपनी वस्तु भेजता है। प्रपत्र 2 में उपयोगकर्ता ऑब्जेक्ट को बदल सकता है और जब वे विंडो को बंद करते हैं, तो अपडेट की गई वस्तु को पहले ViewModel में वापस भेजा जाएगा। क्या आपके पास इसका कोई हल है?
एहसान

2

मुझे लगता है कि दृश्य मॉडल से घटना को संभालने के लिए कोड हो सकता है।

ईवेंट / परिदृश्य के आधार पर, यह एक इवेंट ट्रिगर भी हो सकता है जो मॉडल ईवेंट को देखने के लिए सब्सक्राइब करता है, और प्रतिक्रिया में आह्वान करने के लिए एक या अधिक कार्रवाई करता है।


2

मेरे पास एक ही स्थिति थी और मैसेजबॉक्स को एक डिजाइनर अदृश्य नियंत्रण में लपेट दिया। विवरण मेरे ब्लॉग में हैं

http://geekswithblogs.net/mukapu/archive/2010/03/12/user-prompts-messagebox-with-mvvm.aspx

इसे किसी भी मोडल संवाद, फ़ाइल ब्राउज़ नियंत्रण आदि के लिए बढ़ाया जा सकता है।



1

कार्ल शिफलेट ने सर्विस अप्रोच और प्रिज्म इंटरएक्शनरेंसिएस्ट एप्रोच का उपयोग करके डायलॉग बॉक्स दिखाने के लिए एक नमूना एप्लिकेशन बनाया है।

मुझे सेवा दृष्टिकोण पसंद है - यह कम लचीला है इसलिए उपयोगकर्ताओं को कुछ तोड़ने की संभावना कम है :) यह मेरे आवेदन के WinForms भाग (MessageBox.Show) के साथ भी संगत है, लेकिन अगर आप बहुत सारे अलग-अलग संवाद दिखाने की योजना बनाते हैं, तो सहभागिता है बेहतर रास्ता है।

http://karlshifflett.wordpress.com/2010/11/07/in-the-box-ndash-mvvm-training/


1

मुझे पता है कि यह एक पुराना प्रश्न है, लेकिन जब मैंने यह खोज की, तो मुझे संबंधित प्रश्न बहुत मिले, लेकिन मुझे वास्तव में स्पष्ट प्रतिक्रिया नहीं मिली। इसलिए मैं एक डायलॉगबॉक्स / मैसेजबॉक्स / पॉपिन का अपना कार्यान्वयन करता हूं, और मैं इसे साझा करता हूं!
मुझे लगता है कि यह "MVVM सबूत" है, और मैं इसे सरल और उचित बनाने की कोशिश करता हूं, लेकिन मैं WPF के लिए नया हूं, इसलिए टिप्पणी करने के लिए स्वतंत्र महसूस करता हूं, या पुल अनुरोध भी करता हूं।

https://github.com/Plasma-Paris/Plasma.WpfUtils

आप इसे इस तरह से उपयोग कर सकते हैं:

public RelayCommand YesNoMessageBoxCommand { get; private set; }
async void YesNoMessageBox()
{
    var result = await _Service.ShowMessage("This is the content of the message box", "This is the title", System.Windows.MessageBoxButton.YesNo);
    if (result == System.Windows.MessageBoxResult.Yes)
        // [...]
}

या इस तरह यदि आप अधिक परिष्कृत पॉपिन चाहते हैं:

var result = await _Service.ShowCustomMessageBox(new MyMessageBoxViewModel { /* What you want */ });

और यह इस तरह की चीजें दिखा रहा है:

2


1

मानक दृष्टिकोण

WPF में इस समस्या से निपटने के वर्षों के बाद, मैंने आखिरकार WPF में संवाद को लागू करने के मानक तरीके का पता लगाया । इस दृष्टिकोण के फायदे इस प्रकार हैं:

  1. स्वच्छ
  2. MVVM डिज़ाइन पैटर्न का उल्लंघन नहीं करता है
  3. ViewModal कभी भी UI पुस्तकालयों (WindowBase, PresentationFramework आदि) का संदर्भ नहीं लेता है।
  4. स्वचालित परीक्षण के लिए बिल्कुल सही
  5. संवादों को आसानी से बदला जा सकता है।

तो क्या चाबी है। यह DI + IoC है

यहाँ दिया गया है कि यह कैसे काम करता है। मैं MVVM लाइट का उपयोग कर रहा हूं, लेकिन इस दृष्टिकोण को अन्य रूपरेखाओं तक भी बढ़ाया जा सकता है:

  1. अपने समाधान के लिए एक WPF अनुप्रयोग परियोजना जोड़ें। इसे App कहिए
  2. एक ViewModal क्लास लाइब्रेरी जोड़ें। इसे वीएम कहें
  3. ऐप वीएम प्रोजेक्ट का संदर्भ देता है। VM प्रोजेक्ट ऐप के बारे में कुछ नहीं जानता है।
  4. दोनों परियोजनाओं के लिए MVVM लाइट में NuGet संदर्भ जोड़ें । मैं इन दिनों MVVM लाइट स्टैंडर्ड का उपयोग कर रहा हूं , लेकिन आप पूर्ण फ्रेमवर्क संस्करण के साथ भी ठीक हैं।
  5. VM प्रोजेक्ट में एक इंटरफ़ेस IDialogService जोड़ें :

    public interface IDialogService
    {
      void ShowMessage(string msg, bool isError);
      bool AskBooleanQuestion(string msg);
      string AskStringQuestion(string msg, string default_value);
    
      string ShowOpen(string filter, string initDir = "", string title = "");
      string ShowSave(string filter, string initDir = "", string title = "", string fileName = "");
      string ShowFolder(string initDir = "");
    
      bool ShowSettings();
    }
  6. IDialogServiceअपने प्रकार की सार्वजनिक स्थैतिक संपत्ति को उजागर करें ViewModelLocator, लेकिन प्रदर्शन करने के लिए दृश्य परत के लिए पंजीकरण भाग छोड़ दें। यह कुंजी है :

    public static IDialogService DialogService => SimpleIoc.Default.GetInstance<IDialogService>();
  7. ऐप प्रोजेक्ट में इस इंटरफ़ेस का कार्यान्वयन जोड़ें।

    public class DialogPresenter : IDialogService
    {
        private static OpenFileDialog dlgOpen = new OpenFileDialog();
        private static SaveFileDialog dlgSave = new SaveFileDialog();
        private static FolderBrowserDialog dlgFolder = new FolderBrowserDialog();
    
        /// <summary>
        /// Displays a simple Information or Error message to the user.
        /// </summary>
        /// <param name="msg">String text that is to be displayed in the MessageBox</param>
        /// <param name="isError">If true, Error icon is displayed. If false, Information icon is displayed.</param>
        public void ShowMessage(string msg, bool isError)
        {
                if(isError)
                        System.Windows.MessageBox.Show(msg, "Your Project Title", MessageBoxButton.OK, MessageBoxImage.Error);
                else
                        System.Windows.MessageBox.Show(msg, "Your Project Title", MessageBoxButton.OK, MessageBoxImage.Information);
        }
    
        /// <summary>
        /// Displays a Yes/No MessageBox.Returns true if user clicks Yes, otherwise false.
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool AskBooleanQuestion(string msg)
        {
                var Result = System.Windows.MessageBox.Show(msg, "Your Project Title", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes;
                return Result;
        }
    
        /// <summary>
        /// Displays Save dialog. User can specify file filter, initial directory and dialog title. Returns full path of the selected file if
        /// user clicks Save button. Returns null if user clicks Cancel button.
        /// </summary>
        /// <param name="filter"></param>
        /// <param name="initDir"></param>
        /// <param name="title"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string ShowSave(string filter, string initDir = "", string title = "", string fileName = "")
        {
                if (!string.IsNullOrEmpty(title))
                        dlgSave.Title = title;
                else
                        dlgSave.Title = "Save";
    
                if (!string.IsNullOrEmpty(fileName))
                        dlgSave.FileName = fileName;
                else
                        dlgSave.FileName = "";
    
                dlgSave.Filter = filter;
                if (!string.IsNullOrEmpty(initDir))
                        dlgSave.InitialDirectory = initDir;
    
                if (dlgSave.ShowDialog() == DialogResult.OK)
                        return dlgSave.FileName;
                else
                        return null;
        }
    
    
        public string ShowFolder(string initDir = "")
        {
                if (!string.IsNullOrEmpty(initDir))
                        dlgFolder.SelectedPath = initDir;
    
                if (dlgFolder.ShowDialog() == DialogResult.OK)
                        return dlgFolder.SelectedPath;
                else
                        return null;
        }
    
    
        /// <summary>
        /// Displays Open dialog. User can specify file filter, initial directory and dialog title. Returns full path of the selected file if
        /// user clicks Open button. Returns null if user clicks Cancel button.
        /// </summary>
        /// <param name="filter"></param>
        /// <param name="initDir"></param>
        /// <param name="title"></param>
        /// <returns></returns>
        public string ShowOpen(string filter, string initDir = "", string title = "")
        {
                if (!string.IsNullOrEmpty(title))
                        dlgOpen.Title = title;
                else
                        dlgOpen.Title = "Open";
    
                dlgOpen.Multiselect = false;
                dlgOpen.Filter = filter;
                if (!string.IsNullOrEmpty(initDir))
                        dlgOpen.InitialDirectory = initDir;
    
                if (dlgOpen.ShowDialog() == DialogResult.OK)
                        return dlgOpen.FileName;
                else
                        return null;
        }
    
        /// <summary>
        /// Shows Settings dialog.
        /// </summary>
        /// <returns>true if User clicks OK button, otherwise false.</returns>
        public bool ShowSettings()
        {
                var w = new SettingsWindow();
                MakeChild(w); //Show this dialog as child of Microsoft Word window.
                var Result = w.ShowDialog().Value;
                return Result;
        }
    
        /// <summary>
        /// Prompts user for a single value input. First parameter specifies the message to be displayed in the dialog 
        /// and the second string specifies the default value to be displayed in the input box.
        /// </summary>
        /// <param name="m"></param>
        public string AskStringQuestion(string msg, string default_value)
        {
                string Result = null;
    
                InputBox w = new InputBox();
                MakeChild(w);
                if (w.ShowDialog(msg, default_value).Value)
                        Result = w.Value;
    
                return Result;
        }
    
        /// <summary>
        /// Sets Word window as parent of the specified window.
        /// </summary>
        /// <param name="w"></param>
        private static void MakeChild(System.Windows.Window w)
        {
                IntPtr HWND = Process.GetCurrentProcess().MainWindowHandle;
                var helper = new WindowInteropHelper(w) { Owner = HWND };
        }
    }
  8. हालांकि इनमें से कुछ कार्य सामान्य ( ShowMessage, AskBooleanQuestionआदि) हैं, अन्य इस परियोजना के लिए विशिष्ट हैं और कस्टम Windowएस का उपयोग करते हैं । आप एक ही फैशन में अधिक कस्टम विंडो जोड़ सकते हैं। कुंजी यूआई-विशिष्ट तत्वों को दृश्य परत में रखने के लिए है और वीएमओ परत में पीओसीओ का उपयोग करके लौटाए गए डेटा को उजागर करें
  9. इस श्रेणी का उपयोग करके देखें परत में IoC अपना इंटरफ़ेस पंजीकृत करें। आप इसे अपने मुख्य दृश्य के निर्माता ( InitializeComponent()कॉल के बाद ) में कर सकते हैं:

    SimpleIoc.Default.Register<IDialogService, DialogPresenter>();
  10. तुम वहाँ जाओ। अब आपके पास VM और View दोनों ही लेयर्स पर अपने सभी डायलॉग फंक्शनल की एक्सेस है। आपकी VM परत इन कार्यों को इस तरह कह सकती है:

    var NoTrump = ViewModelLocator.DialogService.AskBooleanQuestion("Really stop the trade war???", "");
  11. इसलिए आप साफ देखिए। VM लेयर को इस बारे में कुछ नहीं पता है कि UI परत द्वारा उपयोगकर्ता के लिए हां / ना में कोई प्रश्न कैसे प्रस्तुत किया जाएगा और फिर भी संवाद से दिए गए परिणाम के साथ सफलतापूर्वक काम कर सकता है।

अन्य मुक्त भत्तों

  1. यूनिट टेस्ट लिखने के लिए, आप IDialogServiceअपने टेस्ट प्रोजेक्ट में कस्टम कार्यान्वयन प्रदान कर सकते हैं और उस क्लास को IoC में रजिस्टर कर सकते हैं , जो कंस्ट्रक्टर आपके टेस्ट क्लास में है।
  2. आपको Microsoft.Win32ओपन और सेव डायलॉग एक्सेस करने के लिए कुछ नामस्थानों को आयात करने की आवश्यकता होगी । मैंने उन्हें छोड़ दिया है क्योंकि इन संवादों का एक WinForms संस्करण भी उपलब्ध है, और कोई व्यक्ति अपना संस्करण बनाना चाहता है। यह भी ध्यान दें कि उपयोग किए गए कुछ पहचानकर्ता DialogPresenterमेरी स्वयं की खिड़कियों के नाम हैं (उदाहरण के लिए SettingsWindow)। आपको उन्हें इंटरफ़ेस और कार्यान्वयन दोनों से निकालने की आवश्यकता होगी या अपनी स्वयं की खिड़कियां प्रदान करनी होंगी।
  3. यदि आपका वीएम मल्टी-थ्रेडिंग करता है, तो DispatcherHelper.Initialize()अपने एप्लिकेशन के जीवन चक्र में एमवीवीएम लाइट को जल्दी कॉल करें ।
  4. सिवाय इसके DialogPresenterकि व्यू लेयर में इंजेक्ट किया गया है, अन्य ViewModals को पंजीकृत होना चाहिए ViewModelLocatorऔर फिर व्यू लेयर को उपभोग करने के लिए उस प्रकार की सार्वजनिक स्थैतिक संपत्ति को उजागर किया जाना चाहिए। कुछ इस तरह:

    public static SettingsVM Settings => SimpleIoc.Default.GetInstance<SettingsVM>();
  5. अधिकांश भाग के लिए, आपके संवादों में डेटा कोडनटेक्स्ट आदि को बांधने या सेट करने के लिए कोई कोड-पीछे नहीं होना चाहिए। आपको चीजों को कंस्ट्रक्टर पैरामीटर के रूप में भी पास नहीं करना चाहिए। एक्सएएमएल आपके लिए यह सब कर सकता है, जैसे:

    <Window x:Class="YourViewNamespace.SettingsWindow"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:local="clr-namespace:YourViewProject"
      xmlns:vm="clr-namespace:YourVMProject;assembly=YourVMProject"
      DataContext="{x:Static vm:ViewModelLocator.Settings}"
      d:DataContext="{d:DesignInstance Type=vm:SettingsVM}" />
  6. DataContextइस तरह से स्थापित करने से आपको सभी प्रकार के डिज़ाइन-टाइम लाभ मिलते हैं जैसे कि इंटेलीसेन्स और ऑटो-पूर्ण।

आशा है कि सभी की मदद करता है।


0

मैं एक ऐसी ही समस्या को हल कर रहा था जब पूछ रहा था कि किसी कार्य या संवाद के लिए दृश्य मॉडल कैसा दिखना चाहिए

मेरा वर्तमान समाधान इस तरह दिखता है:

public class SelectionTaskModel<TChoosable> : ViewModel
    where TChoosable : ViewModel
{
    public SelectionTaskModel(ICollection<TChoosable> choices);
    public ReadOnlyCollection<TChoosable> Choices { get; }
    public void Choose(TChoosable choosen);
    public void Abort();
}

जब दृश्य मॉडल यह तय करता है कि उपयोगकर्ता इनपुट की आवश्यकता है, तो यह SelectionTaskModelउपयोगकर्ता के लिए संभावित विकल्पों के साथ एक उदाहरण को खींचता है । बुनियादी ढांचा संबंधित दृश्य को लाने का ख्याल रखता है, जो उचित समय Choose()में उपयोगकर्ता की पसंद के साथ फ़ंक्शन को कॉल करेगा ।


0

मैं उसी समस्या से जूझता रहा। मैं View और ViewModel के बीच में अंतर करने का एक तरीका लेकर आया हूं। आप एक संदेश बॉक्स दिखाने के लिए यह बताने के लिए ViewModel से दृश्य पर एक संदेश भेजने की पहल कर सकते हैं और यह परिणाम के साथ वापस रिपोर्ट करेगा। तब ViewModel View से दिए गए परिणाम पर प्रतिक्रिया दे सकता है।

मैं अपने ब्लॉग में इसे प्रदर्शित करता हूं :


0

मैंने इस विषय के बारे में काफी व्यापक लेख लिखा है और MVVM डायलॉग के लिए एक पॉप-इन लाइब्रेरी भी विकसित की है। एमवीवीएम के लिए सख्त पालन न केवल संभव है, बल्कि ठीक से लागू होने पर बहुत साफ है, और इसे आसानी से तीसरे पक्ष के पुस्तकालयों तक बढ़ाया जा सकता है जो स्वयं इसका पालन नहीं करते हैं:

https://www.codeproject.com/Articles/820324/Implementing-Dialog-Boxes-in-MVVM


0

क्षमा करें, लेकिन मुझे इसमें झंकार करना है। मैं प्रिज्म प्रोजेक्ट में Prism.Wpf.Interactivity namespace खोजने से पहले, कई सुझाए गए समाधानों के माध्यम से रहा हूं। आप संपर्क अनुरोधों और पॉपअप विंडो कार्रवाई का उपयोग या तो कस्टम विंडो को रोल करने के लिए कर सकते हैं या सरल आवश्यकताओं के लिए अधिसूचना और पुष्टिकरण पॉपअप में बनाए गए हैं। ये सच्ची खिड़कियां बनाते हैं और इस तरह प्रबंधित होते हैं। आप संवाद में किसी भी निर्भरता के साथ एक संदर्भ वस्तु पास कर सकते हैं। मैंने इस समाधान का उपयोग अपने काम में किया क्योंकि मैंने इसे पाया। हमारे यहां कई वरिष्ठ देव हैं और कोई भी व्यक्ति कुछ भी बेहतर नहीं कर पाया है। हमारा पिछला समाधान एक उपरिशायी में संवाद सेवा था और इसे बनाने के लिए एक प्रस्तुतकर्ता वर्ग का उपयोग करना था, लेकिन आपके पास सभी संवाद दृश्यमॉडल आदि के लिए कारखाने होने चाहिए थे।

यह तुच्छ नहीं है, लेकिन यह भी सुपर जटिल नहीं है। और यह प्रिज्म के लिए बनाया गया है और इसलिए सबसे अच्छा (या बेहतर) अभ्यास IMHO है।

मेरे 2 सेंट!


-1

संपादित करें: हाँ, मैं मानता हूं कि यह एक सही एमवीवीएम दृष्टिकोण नहीं है और मैं अब कुछ इसी तरह का उपयोग कर रहा हूं जो कि अंधों द्वारा सुझाया गया है।

एक तरीका यह हो सकता है

आपके मुख्य दृश्य मॉडल में (जहाँ आप मोडल खोलते हैं):

void OpenModal()
{
    ModalWindowViewModel mwvm = new ModalWindowViewModel();
    Window mw = new Window();
    mw.content = mwvm;
    mw.ShowDialog()
    if(mw.DialogResult == true)
    { 
        // Your Code, you can access property in mwvm if you need.
    }
}

और आपके मोडल विंडो में / ViewModel:

XAML:

<Button Name="okButton" Command="{Binding OkCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}">OK</Button>
<Button Margin="2" VerticalAlignment="Center" Name="cancelButton" IsCancel="True">Cancel</Button>

ViewModel:

public ICommand OkCommand
{
    get
    {
        if (_okCommand == null)
        {
            _okCommand = new ActionCommand<Window>(DoOk, CanDoOk);
        }
        return _okCommand ;
    }
}

void DoOk(Window win)
{
    <!--Your Code-->
    win.DialogResult = true;
    win.Close();
}

bool CanDoOk(Window win) { return true; }

WPF MVVM यहाँ क्या पोस्ट किया गया है : खिड़की कैसे बंद करें


2
मैं नीच नहीं था, लेकिन मुझे संदेह है क्योंकि दृश्य-मॉडल का दृश्य के लिए सीधा संदर्भ है।
ब्रायन गिदोन

@BrianGideon, आपकी टिप्पणी के लिए धन्यवाद। मैं मानता हूं कि यह एक विघटित समाधान नहीं है। वास्तव में, मैं अंधभक्ति द्वारा सुझाए गए घाट के समान कुछ भी उपयोग नहीं कर रहा हूं। एक बार फिर धन्यवाद।
सिमोन

जब यह इतना आसान नहीं है तो इसे देखने में पहुंचने के लिए बुरा रूप है।
बजे क्रिस बॉर्डमैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.