2009-07-24 11 views
45

मेरे पास एक दृश्य है जिसमें एक TextBox और इसके नीचे Button एस है। जब खिड़की लोड होती है तो मैं ध्यान केंद्रित करने के लिए TextBox चाहता हूं।लोड पर WPF एमवीवीएम फोकस फ़ील्ड

यदि मैं एमवीवीएम का उपयोग नहीं कर रहा था तो मैं लोड किए गए ईवेंट में TextBox.Focus() पर कॉल करूंगा। हालांकि मेरे व्यूमोडेल को मेरे विचार के बारे में पता नहीं है, तो मैं अपने विचार के कोडबेंड में कोड डाले बिना इसे कैसे पूरा कर सकता हूं?

संपादित करें: जवाब पढ़ने के बाद मैं इस मैं शायद जॉन गैलोवे के जवाब की सिफारिश करेंगे, क्योंकि यह से नियंत्रित किया जा सकता से प्रारंभिक पृष्ठ फोकस अन्य कुछ भी थे, तो दृश्य XAML

<DockPanel FocusManager.FocusedElement="{Binding ElementName=MessageTextBox}">  
    <TextBox Name="MessageTextBox" Text="{Binding Message}"/> 
</DockPanel> 

में इस कोड डाल करने का निर्णय लिया ViewModel।

उत्तर

44

यह आप बेहतर महसूस एक संलग्न संपत्ति का उपयोग कर आप Xaml में ऐसा कर सकते हैं (यह मुझे बेहतर महसूस करता है) करता है:

http://msdn.microsoft.com/en-us/library/system.windows.input.focusmanager.focusedelement.aspx

कुछ भी आप codebehind में कर सकते हैं आप Xaml में क्या कर सकते हैं अगर आप चाल पता है। सौभाग्य से, आपको इस चाल को लागू करने की आवश्यकता नहीं थी - एमएस ने आपके लिए यह किया था।

+0

यही वही है जो मैं ढूंढ रहा था। मुझे लगता है कि यह कोड दृश्य में है और किसी कारण से मुझे कोड के पीछे xaml में बेहतर पसंद है। –

+2

गैलोवे का सुझाव आपको व्यूमोडेल से फ़ोकस को नियंत्रित करने की अनुमति देता है ... आप उस पर भी नज़र डाल सकते हैं। –

+3

कुछ अन्य उत्तरों को पढ़ने के बाद मुझे यकीन नहीं है कि कोड ViewModel में है। ऐसा लगता है कि सीधे देखने के लिए बंधे हैं। अगर मेरे पास एक और जटिल पृष्ठ था जो वास्तव में अन्य घटनाओं के आधार पर ध्यान केंद्रित कर रहा था जो शायद समझ में आएंगे। उस ने कहा कि यह अभी भी एक अच्छी चाल है। –

14

इस मामले में मुझे लगता है कि कोड को दृश्य में रखना ठीक है। नियंत्रण में फोकस सेट करना एप्लिकेशन के तर्क के बजाय उपयोगकर्ता इंटरफ़ेस के व्यवहार को प्रभावित करता है और इसलिए दृश्य की ज़िम्मेदारी है।

+1

मैं क्या सोचा था की तरह है कि। हर बार जब मैं दृश्य में कोड जोड़ने के बारे में सोचता हूं तो मुझे थोड़ा गंदा लग रहा है। इस मामले में हालांकि यह समझ में आता है। –

+14

मुझे लगता है कि एक बार जब मैंने अपना एमवीवीएम दर्शन "कोई कोड पीछे" से "न्यूनतम और प्रासंगिक कोड" के पीछे बदल दिया, तो मेरा जीवन बहुत आसान हो गया। मैंने एंड्रॉइड इमेस के संलग्न संपत्ति के बारे में नहीं सुना था, और यह आपके पीछे दिए गए कोड के खराब स्वाद के लिए एक अच्छा समाधान की तरह लगता है, लेकिन * वैध *, गैर-तर्क कोड डालने से डरो मत यूआई। –

+4

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

4

मैं फोकस के साथ नियंत्रण को बहुत अधिक "दृश्य केवल" होने पर विचार करता हूं, इसलिए कोड के पीछे होने में कोई समस्या नहीं होगी।

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

8

वास्तव में, यूआई चिंता पर ध्यान केंद्रित नहीं है? एमवीवीएम चिंताओं को अलग करने के बारे में है - मॉडल में जो मॉडल है, वह मॉडल में है, जो देखने के लिए है, और कौन सा बाध्य मॉडल और एक साथ देखें व्यूमोडेल में है (यह निश्चित रूप से ओवरम्प्लिफाइड विवरण है)।

इसका मतलब है कि यूआई तर्क दृश्य में रहता है - TextBox.Focus() मेरी राय में, ऐसा करने के लिए उचित तरीका है।

10
  1. अपने व्यूमोडेल में एक संपत्ति है जो इंगित करती है कि वर्तमान में केंद्रित तत्व कौन सा है।
  2. उस संपत्ति से जुड़ने के लिए FocusManager का उपयोग करें।

    <Window FocusManager.FocusedElement="{Binding ElementName=ViewModel.FocusedItem}"/> 
    

आपका ViewModel एक अनुवादक जो पूरी तरह से मौजूद है दृश्य को जानकारी प्रदान करने के लिए है, तो आप जोड़ सकते हैं कि देखें ढंग से काम करने की जरूरत है वी एम के लिए जो भी जानकारी है।

+4

लेकिन फिर आपको अपने सभी तत्वों का नाम देना होगा और वीएम में उस नाम का उपयोग करना होगा। यह काम नहीं करेगा यदि आपके पास वीएम में वस्तुओं का संग्रह है जो दृश्य बाध्यकारी है। – Carlos

+7

आईएमएचओ, वीएम को वास्तविक दृश्य कार्यान्वयन में नियंत्रण नामों या प्रकारों के बारे में कोई जानकारी नहीं होनी चाहिए। इसके बजाय मैं दृश्य को वीएम से एक संपत्ति परिवर्तन अधिसूचना के लिए सुनना चाहता हूं और फिर इसे इसे संभालने देता हूं। जैसे ActivateNameField सच हो जाता है .. दृश्य प्रासंगिक नियंत्रण पाता है और उस पर ध्यान केंद्रित करता है। – Gishu

+1

मैं मानता हूं कि व्यापार तर्क शामिल होने पर वीएम की प्रक्रिया में एक भूमिका होनी चाहिए। एक बार डिज़ाइन कॉल करने के लिए "जब वे इस चेकबॉक्स का चयन करते हैं और वे एक व्यवस्थापक होते हैं तो ओवरराइड रीजन टेक्स्टबॉक्स पर फ़ोकस सेट करते हैं" तो तर्क VM में होता है। यह चाल संपत्ति परिवर्तन का सम्मान करने के लिए दृश्य प्राप्त कर रही है। – TheZenker

2

'डब्ल्यूपीएफ प्रारंभिक फोकस दुःस्वप्न' होने के बाद और स्टैक पर कुछ उत्तरों के आधार पर, निम्नलिखित मेरे लिए सबसे अच्छा समाधान साबित हुआ।

सबसे पहले, अपना ऐप जोड़ें।XAML OnStartup() निम्नलिखित: कुछ ढांचे की वजह से

void WindowLoaded(object sender, RoutedEventArgs e) 
    { 
     var window = e.Source as Window; 
     System.Threading.Thread.Sleep(100); 
     window.Dispatcher.Invoke(
     new Action(() => 
     { 
      window.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); 

     })); 
    } 

सूत्रण मुद्दा WPF प्रारंभिक ध्यान के रूप में इस्तेमाल किया जाना चाहिए ज्यादातर विफल रहता है:

EventManager.RegisterClassHandler(typeof(Window), Window.LoadedEvent, 
      new RoutedEventHandler(WindowLoaded)); 

फिर 'WindowLoaded' घटना भी App.xaml में जोड़ने दौर कि शर्ते।

मुझे निम्न समाधान सबसे अच्छा मिला क्योंकि यह पूरे ऐप के लिए वैश्विक स्तर पर उपयोग किया जाता है।

आशा है कि यह मदद करता है ...

ओरान

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