2012-04-16 15 views
8

this article पढ़ने के बाद, एक मेरी PersonViewModel वर्ग में निम्नलिखित कोड है:wpf में ViewModel गुणों को त्वरित रूप से उत्पन्न करना?

public Jurisdiction CountryResidence 
{ 
    get 
    { 
     return Model.CountryResidence; 
    } 
    set 
    { 
     if (Model.CountryResidence == value) 
      return; 
     else 
     { 
      Model.CountryResidence = value; 
      base.OnPropertyChanged("CountryResidence"); 
     } 
    } 
} 

public Jurisdiction CountryBirth 
{ 
    get 
    { 
     return Model.CountryBirth; 
    } 
    set 
    { 
     if (Model.CountryBirth == value) 
      return; 
     else 
     { 
      Model.CountryBirth = value; 
      base.OnPropertyChanged("CountryBirth"); 
     } 
    } 
} 

मैं भी एक प्रारूप वाले CountryDomiciled, CountryPassport और LegalJurisdiction, सभी की है। इसी तरह, मेरे पास String गुण हैं, जिनमें से सभी अपना प्रारूप साझा करते हैं।

इसके परिणामस्वरूप बहुत सारे कोड हैं! हालांकि, मैं यह और अधिक संक्षिप्त बनाने के लिए काम नहीं कर सकता।

क्या इन गुणों को उत्पन्न करने का कोई बेहतर तरीका है जो उन्हें दृढ़ता से टाइप करता है?

+1

+1 वाक्यांश "samey कोड" शब्द को गढ़ने के लिए! मुझे इसका इस्तेमाल करना होगा। – Zannjaminderson

+2

यदि आप सी # 5 का उपयोग कर रहे हैं, तो आप कुछ विशेषताओं के साथ कुछ बॉयलरप्लेट कोड से छुटकारा पा सकते हैं।यहां देखें: http://bhrnjica.net/2012/03/18/new-feature-in-c-5-0-callermembername/ – Vlad

+0

@Vlad धन्यवाद, यह साफ दिखता है। इस मामले में हालांकि सभी सी # 5 मुझे 'ऑनप्रॉपर्टी चेंज' से स्ट्रिंग को हटाने की क्षमता देता है, है ना? – Oliver

उत्तर

4

अद्यतन: NotifyPropertyWeaver बहिष्कृत है और PropertyChanged.Fody के रूप में अपनी जीवन जारी है। यह इस मुद्दे को हल करने के लिए एक पूर्ण सुपर शानदार तरीका है। यह एक संकलन समय केवल समाधान है।

यहाँ कुछ है कि आप कोड और मुसीबत बचत होगी है: ऊपर का उपयोग करना, आप किसी भी INotifyPropertyChanged संबंधित कोड के बिना अपने गुण लागू कर सकते हैं NotifyPropertyWeaver

, और एक निर्माण कदम आप के लिए तारों अप संभाल लेंगे।

यह एक साधारण प्रोजेक्ट (Nuget के माध्यम से भी उपलब्ध है) शामिल है जो स्वचालित रूप से कॉलबैक को किसी भी वर्ग के गुणों में इंजेक्ट करेगा जो INotifyPropertyChanged लागू करता है। यह संकलन समय पर करता है (इसलिए कोई रनटाइम हिट नहीं) और आपके कोड में केवल ऑटो-कार्यान्वित गुण हो सकते हैं (आपके मामले में छोड़कर, जहां आप एक अलग बैकिंग ऑब्जेक्ट का उपयोग कर रहे हैं)।

इसमें मूल्य समानता जांच भी शामिल है, इसलिए इसमें पूर्ण तर्क शामिल है। मैंने मैन्युअल रूप से कार्यान्वित गुणों के साथ इसका परीक्षण नहीं किया है, लेकिन जांच करने लायक है।

संपादित करें: मैंने अब इसका परीक्षण किया है, और यह ठीक काम करता है: मैन्युअल रूप से कार्यान्वित संपत्ति "बस काम करेगी।"

+0

लेखक ने मेरे उत्तर में यह टिप्पणी की: "हालांकि, मैं एक तरीका पसंद करूंगा जो एक ही स्थान पर साझा कार्यक्षमता को रखता है, यदि यह संभव है, तो प्रत्येक संपत्ति के लिए इसे क्लोन करने के बजाय" । आपका उत्तर इस आवश्यकता को कैसे हल करता है? हालांकि मैं आपकी पोस्ट को वोट नहीं दूंगा। – EvAlex

+0

@EvAlex - "इसे एक ही स्थान पर रखने" की आवश्यकता रखरखाव लागत को कम करना है, क्योंकि यह सभी कोड के साथ है। लेकिन एक एओपी दृष्टिकोण के साथ कोई कोड नहीं होगा जिसे डेवलपर द्वारा बनाए रखा जाना चाहिए। इस संबंध में एओपी आवश्यक कोड इंजेक्ट कैसे करता है इसका कोई परिणाम नहीं है। –

0

क्या आपने विजुअल स्टूडियो कोड स्निपेट्स जैसे prop या propfull का उपयोग करने का प्रयास नहीं किया है? बस इसे टाइप करें और टैब कुंजी दो बार दबाएं। समस्या propfull स्निपेट संपत्ति नहीं बढ़ाया ईवेंट।

लेकिन वास्तव में ऐसे कार्य के लिए तीसरे पक्ष के स्निपेट होना चाहिए। यहां मैंने जो पाया है: property snippet with INPC

+0

धन्यवाद, मैंने पहले इन्हें नहीं देखा है - वे वास्तव में साफ दिखते हैं। हालांकि, मैं एक तरीका पसंद करूंगा जो साझा की कार्यक्षमता को एक ही स्थान पर रखता है, यदि यह संभव है, तो प्रत्येक संपत्ति के लिए इसे क्लोन करने के बजाय। – Oliver

+0

यह प्रश्न में समस्या का समाधान नहीं करता है, क्योंकि आपको अभी भी कोड को डुप्लिकेट करना है। –

+0

@Dan Puzey प्रश्न में कोड डुप्लिकेशन के बारे में कोई बात नहीं थी। "क्या इन गुणों को उत्पन्न करने का कोई बेहतर तरीका है जो उन्हें दृढ़ता से टाइप करता है?"। मैंने जवाब दिया: "कोड स्निपेट्स है"। अधिक कुशल कार्यान्वयन के लिए – EvAlex

1

मुझे किसी भी अंतर्निहित तरीके से पता नहीं है, लेकिन आप एक मैक्रो रिकॉर्ड कर सकते हैं जो आपके लिए कोड उत्पन्न करेगा। मुझे ऐसा करने का सबसे आसान तरीका है कि केवल एक मैक्रो रिकॉर्ड करना शुरू करें, फिर केवल कीबोर्ड का उपयोग करके जो कुछ भी आप चाहते हैं उसे बनाएं (आप आसान कीबोर्ड शॉर्टकट्स here की एक सूची पा सकते हैं)

उदाहरण के लिए, मेरे पास ऐसा कोई है जो उत्पन्न करता है किसी संपत्ति का सार्वजनिक संस्करण, इसलिए मुझे टाइप करना है private string _someValue; और मेरे मैक्रो को दबाएं, और यह संपत्ति परिवर्तन अधिसूचना के साथ सार्वजनिक संपत्ति उत्पन्न करेगा।

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

public Model SomeModel 
{ 
    get 
    { 
     return Model; 
    } 
    set 
    { 
     if (Model == value) 
      return; 
     else 
     { 
      Model= value; 
      base.OnPropertyChanged("SomeModel"); 
     } 
    } 
} 

और इस तरह मॉडल के गुण के लिए बाध्य:

<TextBox Text="{Binding SomeModel.SomeProperty}" /> 
2

आप के लिए वास्तव में क्या चाहते हैं, लेकिन एक के रूप में अलग है कि आप अपने तर्क परीक्षण उलट कर संपत्ति प्रति दो पंक्तियों बचा सकते हैं:

public Jurisdiction CountryResidence 
{ 
    get 
    { 
     return Model.CountryResidence; 
    } 
    set 
    { 
     if (Model.CountryResidence != value) 
     { 
      Model.CountryResidence = value; 
      base.OnPropertyChanged("CountryResidence"); 
     } 
    } 
} 
+0

+1। –

+0

मैं इसे +1 कर दूंगा, लेकिन वास्तव में यह सवाल का जवाब नहीं देता है, इसलिए मैं नहीं जा रहा हूं। यह एक टिप्पणी के रूप में बेहतर होगा। – Rachel

+0

सहमत हैं, इसे कभी भी पूर्ण उत्तर के रूप में नहीं बनाया गया है। इसे शीर्ष बनाने के लिए दान को उखाड़ फेंक दिया है। जटिल एमएसआईएल पीढ़ी के ढांचे पर स्निपेट के लिए – GazTheDestroyer

8

मैं विजुअल स्टूडियो के लिए स्निपेट का उपयोग करता हूं, जो बैकिंग स्टोरेज और मेरे लिए इवेंट बढ़ाने के साथ संपत्ति उत्पन्न करता है। सीधे शब्दों में (या अन्य नाम यदि आप चाहें) नाम propchanged साथ xml फ़ाइल बना सकते हैं और सामग्री निम्नलिखित:

<?xml version="1.0" encoding="utf-8" ?> 
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> 
    <CodeSnippet Format="1.0.0"> 
    <Header> 
     <Title>propchanged</Title> 
     <Shortcut>propchanged</Shortcut> 
     <Description>Code snippet for property (with call to OnPropertyChanged) and backing field</Description> 
     <Author>lazyberezovsky</Author> 
     <SnippetTypes> 
     <SnippetType>Expansion</SnippetType> 
     </SnippetTypes> 
    </Header> 
    <Snippet> 
     <Declarations> 
     <Literal> 
      <ID>type</ID> 
      <ToolTip>Property type</ToolTip> 
      <Default>string</Default> 
     </Literal> 
     <Literal> 
      <ID>property</ID> 
      <ToolTip>Property name</ToolTip> 
      <Default>MyProperty</Default> 
     </Literal> 
     <Literal> 
      <ID>field</ID> 
      <ToolTip>The variable backing this property</ToolTip> 
      <Default>myVar</Default> 
     </Literal> 
     </Declarations> 
     <Code Language="csharp"> 
     <![CDATA[private $type$ $field$; 

    public $type$ $property$ 
    { 
     get { return $field$;} 
     set 
    { 
     if ($field$ == value) 
      return; 

     $field$ = value; 
     OnPropertyChanged("$property$"); 
    } 
    } 
    $end$]]> 
     </Code> 
    </Snippet> 
    </CodeSnippet> 
</CodeSnippets> 

और C:\Users\YourName\Documents\Visual Studio 2010\Code Snippets\Visual C#\My Code Snippets\ फ़ोल्डर में डाल दिया।

अगला, मैं कुछ बेस व्यू मॉडेल से अपने व्यू मॉडल्स का उत्तराधिकारी हूं, जो INotifyPropertyChanged इंटीफेस लागू करता है और `PropertyChanged 'ईवेंट उत्पन्न करने के लिए संरक्षित विधि OnPropertyChanged प्रदान करता है।

public class ViewModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName); 
    } 
} 

अब जब आप दृश्य स्टूडियो में propchanged लिखते हैं, तो आप संपत्ति प्रकार और नाम के लिए पूछना, और आप के लिए कोड जनरेट करेगा।

public class PersonViewModel : ViewModel 
{ 
    // type here 'propchanged' (or other shortcut assigned for snippet) 
} 

अद्यतन:

एक अन्य विकल्प PostSharp तरह AOP ढांचे द्वारा कोड पैदा कर रहा है। इस मामले में संकलन के दौरान कोड उत्पन्न और जोड़ा जाएगा (इस प्रकार आपकी कक्षाएं साफ रहेंगी)। Here को लागू करने INotifyProperty PostSharp के द्वारा बदले की उदाहरण है विशेषताओं:

[Notify] 
public class PersonViewModel 
{ 
    public Jurisdiction CountryResidence { get; set; } 
    public Jurisdiction CountryBirth { get; set; } 
} 
+1

+1। इसे सरल stoopid रखें! –

+1

उत्कृष्ट स्निपेट जिसे व्यक्तिगत जरूरतों के हिसाब से समायोजित किया जा सकता है + – usefulBee

1

संपत्ति नाम (जिसे रिफैक्टरिंग सक्षम करने के लिए आवश्यक है) के "मजबूत टाइप किए गए" संदर्भ प्राप्त करने के लिए, आप अभिव्यक्तियों का उपयोग कर सकते हैं। अपने ViewModels के लिए एक आधार वर्ग में निम्न विधि रखो, शायद:

public Jurisdiction CountryResidence 
{ 
    get { return Model.CountryResidence; } 
    set 
    {   
     if (Model.CountryResidence == value) 
      return; 

     Model.CountryResidence = value; 
     OnPropertyChanged(() => CountryResidence); 
    } 
} 

अब, रिफैक्टरिंग संपत्ति के नाम स्वचालित रूप से कर रहे हैं:

protected void RaisePropertyChanged<T>(Expression<Func<T>> property) 
{ 
    var handler = PropertyChanged; 
    if (handler == null) return; 

    var propertyName = NotifyPropertyChangedHelper.GetPropertyNameFromExpression(property); 
    handler(sender, new PropertyChangedEventArgs(propertyName)); 
} 

अपने ViewModels में, आप तो निम्न कार्य करने में सक्षम हो जाएगा संदर्भ के बाद वास्तविक संपत्ति के खिलाफ है।

यह हार्डकोडिंग संपत्ति नामों के दर्द बिंदु को हल करता है, हालांकि इसे अभी भी बॉयलरप्लेट कोड की 4-5 लाइनों की आवश्यकता होती है। notifypropertyweaver और PostSharp जैसे पहलू-उन्मुख दृष्टिकोण वास्तव में सभी व्यूमोडेल में मैन्युअल कोडिंग को हटा देता है।

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