2008-12-07 13 views
5

मैं विंडोज फॉर्म एप्लिकेशन के लिए लोड/सेव फ़ंक्शन को लागू करने का प्रयास कर रहा हूं।सहेजें/लोड कार्यक्षमता को लागू करने का तरीका क्या है?

मुझे मिल गया है निम्न घटक:

  • एक ट्री दृश्य
  • सूची के एक जोड़े को विचार
  • पाठ खानों में से एक जोड़े को
  • वस्तुओं के एक जोड़े को (जो एक बड़ा dictionarylist रखती है)

मैं इसे सभी को फ़ाइल में सहेजने के लिए एक तरीका लागू करना चाहता हूं, और बाद में इसे फिर से लोड/लोड करना चाहता हूं।

ऐसा करने का सबसे अच्छा तरीका क्या है?

मुझे लगता है कि एक्सएमएल क्रमबद्धता जाने का रास्ता है, लेकिन मुझे पूरा यकीन नहीं है कि कैसे, या कहां से शुरू किया जाए। या क्या ऐसा करने में सक्षम होने के लिए इसे वास्तव में जटिल समाधान की आवश्यकता होगी?

उत्तर

6

यहां एक उदाहरण है जो यूआई में किसी ऑब्जेक्ट और कुछ पूर्वजों को बांधता है; यहां सी # 3.0 का उपयोग पूरी तरह से ब्रेवटी के लिए है - सब कुछ सी # 2.0 के साथ भी काम करेगा। महत्वपूर्ण बात , वहाँ अद्यतन करने ऑब्जेक्ट मॉडल, या ऑब्जेक्ट मॉडल से यूआई के लिए समर्पित किसी भी कोड नहीं है -

कोड यहाँ के अधिकांश रूप स्थापित कर रही है, और/या संपत्ति परिवर्तन सूचनाओं के साथ काम यूआई से।

यह भी ध्यान रखें आईडीई डेटा-बाइंडिंग कोड का एक बहुत आप के लिए, बस संपत्ति ग्रिड में प्रपत्र पर एक BindingSource छोड़ने और संवाद के माध्यम से एक प्रकार के डेटा स्रोत की स्थापना करके कर सकते हैं।

ध्यान दें कि यह जरूरी संपत्ति परिवर्तन प्रदान करने के लिए सूचनाएं (PropertyChanged सामान) नहीं है - हालांकि, सबसे 2 तरह यूआई बंधन काफी बेहतर यदि आप ऐसा काम करेंगे यह लागू। ऐसा नहीं है कि पोस्टशर्प में कुछ न्यूनतम कोड के साथ ऐसा करने के दिलचस्प तरीके हैं।

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.IO; 
using System.Windows.Forms; 
using System.Xml.Serialization; 
static class Program { // formatted for vertical space 
    [STAThread] 
    static void Main() { 
     Application.EnableVisualStyles(); 

     Button load, save, newCust; 
     BindingSource source = new BindingSource { DataSource = typeof(Customer) }; 
     XmlSerializer serializer = new XmlSerializer(typeof(Customer)); 
     using (Form form = new Form { 
      DataBindings = {{"Text", source, "Name"}}, // show customer name as form title 
      Controls = { 
       new DataGridView { Dock = DockStyle.Fill, // grid of orders 
        DataSource = source, DataMember = "Orders"}, 
       new TextBox { Dock = DockStyle.Top, ReadOnly = true, // readonly order ref 
        DataBindings = {{"Text", source, "Orders.OrderRef"}}}, 
       new TextBox { Dock = DockStyle.Top, // editable customer name 
        DataBindings = {{"Text", source, "Name"}}}, 
       (save = new Button { Dock = DockStyle.Bottom, Text = "save" }), 
       (load = new Button{ Dock = DockStyle.Bottom, Text = "load"}), 
       (newCust = new Button{ Dock = DockStyle.Bottom, Text = "new"}), 
      } 
     }) 
     { 
      const string PATH = "customer.xml"; 
      form.Load += delegate { 
       newCust.PerformClick(); // create new cust when loading form 
       load.Enabled = File.Exists(PATH); 
      }; 
      save.Click += delegate { 
       using (var stream = File.Create(PATH)) { 
        serializer.Serialize(stream, source.DataSource); 
       } 
       load.Enabled = true; 
      }; 
      load.Click += delegate { 
       using (var stream = File.OpenRead(PATH)) { 
        source.DataSource = serializer.Deserialize(stream); 
       } 
      }; 
      newCust.Click += delegate { 
       source.DataSource = new Customer(); 
      }; 
      Application.Run(form); 
     } 
    } 
} 

[Serializable] 
public sealed class Customer : NotifyBase { 
    private int customerId; 
    [DisplayName("Customer Number")] 
    public int CustomerId { 
     get { return customerId; } 
     set { SetField(ref customerId, value, "CustomerId"); } 
    } 

    private string name; 
    public string Name { 
     get { return name; } 
     set { SetField(ref name, value, "Name"); } 
    } 

    public List<Order> Orders { get; set; } // XmlSerializer demands setter 

    public Customer() { 
     Orders = new List<Order>(); 
    } 
} 

[Serializable] 
public sealed class Order : NotifyBase { 
    private int orderId; 
    [DisplayName("Order Number")] 
    public int OrderId { 
     get { return orderId; } 
     set { SetField(ref orderId, value, "OrderId"); } 
    } 

    private string orderRef; 
    [DisplayName("Reference")] 
    public string OrderRef { 
     get { return orderRef; } 
     set { SetField(ref orderRef, value, "OrderRef"); } 
    } 

    private decimal orderValue, carriageValue; 

    [DisplayName("Order Value")] 
    public decimal OrderValue { 
     get { return orderValue; } 
     set { 
      if (SetField(ref orderValue, value, "OrderValue")) { 
       OnPropertyChanged("TotalValue"); 
      } 
     } 
    } 

    [DisplayName("Carriage Value")] 
    public decimal CarriageValue { 
     get { return carriageValue; } 
     set { 
      if (SetField(ref carriageValue, value, "CarriageValue")) { 
       OnPropertyChanged("TotalValue"); 
      } 
     } 
    } 

    [DisplayName("Total Value")] 
    public decimal TotalValue { get { return OrderValue + CarriageValue; } } 
} 

[Serializable] 
public class NotifyBase { // purely for convenience 
    [field: NonSerialized] 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected bool SetField<T>(ref T field, T value, string propertyName) { 
     if (!EqualityComparer<T>.Default.Equals(field, value)) { 
      field = value; 
      OnPropertyChanged(propertyName); 
      return true; 
     } 
     return false; 
    } 
    protected virtual void OnPropertyChanged(string propertyName) { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 
+0

कोड के लिए धन्यवाद, ऐसा लगता है कि यह मेरे quesiton का जवाब है, मैं इस तरह के एक समाधान को लागू करने की कोशिश करेंगे और देखें कि मैं सफलता कर सकता हूं या नहीं। मैंने पोस्टशर्प देखा है, लेकिन मुझे पूरा यकीन नहीं है कि यह जाने का अच्छा तरीका है या नहीं। –

+0

ट्री व्यू दर्द, नोट हैं –

6

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

एक बार जब आप यूआई से डेटा अलग कर लेते हैं, तो डेटा सहेजना आसान होता है। XmlSerializer आदि के लिए बहुत सारे उदाहरण हैं

+0

मुझे पूरा यकीन नहीं है कि यह कैसे करना है, मैंने कभी भी नियंत्रण और कक्षाओं के बीच डेटा-बाइंडिंग का उपयोग नहीं किया (मैं केवल इसे लगातार स्टोरेज, सेटिंग्स इत्यादि के लिए उपयोग करता हूं)। मैं इस पर गौर करूंगा। –

+0

क्या आप मुझे ऑब्जेक्ट्स और नियंत्रणों के बीच बाध्यकारी इस तरह के उदाहरण के लिए एक उदाहरण दे सकते हैं? –

1

हां, आपको निश्चित रूप से इसके लिए एक्सएमएल क्रमबद्धता का उपयोग करना चाहिए। लेकिन जैसा कि मार्क ग्रेवेल ने नोट किया था, आपके पास ऐसी ऑब्जेक्ट्स होनी चाहिए जो आपके जीयूआई घटकों द्वारा प्रदर्शित डेटा को पहले रखें। फिर आप कोड की न्यूनतम पंक्तियों के साथ व्यावहारिक रूप से (डी) धारावाहिक स्वचालित कर सकते हैं।

0

इसका इस्तेमाल करने के लिए काफी तुच्छ है डेटा-बाइंडिंग यूआई के लिए एक ऑब्जेक्ट मॉडल टाई।

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

क्या मुझे एक लोडर लिखना है जो धारावाहिक एक्सएमएल लोड करता है और ऑब्जेक्ट प्राप्त करता है और फिर ऑब्जेक्ट प्राप्त करता है और पूरे जीयूआई को भरता है? जाहिर है मैन्युअल लोडिंग की तरह यह बाध्यकारी नहीं है। क्या मैं कुछ भूल रहा हूँ ?

+0

मैं ट्रेन पर एक साथ उदाहरण दूंगा; कुछ घंटों में वापस पोस्ट करेंगे। देरी के लिए खेद है: आवश्यक नींद ;- –

+0

उदाहरण के लिए धन्यवाद, यह बहुत अच्छा लग रहा है। मैं इसे खोदूँगा। इसके लिए पोस्टशर्प का उपयोग करने पर आपकी राय के बारे में भी उत्सुकता है। –

0

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

http://www.codeproject.com/KB/cs/objserial.aspx

0

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

+0

इस विचार के लिए धन्यवाद, हालांकि जब तक मुझे इसकी पूरी आवश्यकता नहीं है, मैं सबकुछ स्मृति (प्रदर्शन मुद्दों) में रखता हूं, हालांकि मुझे लगता है कि एडीओ.NET को स्मृति पर संरचनाओं का कुछ प्रकार का समर्थन मिला है। –

1

उपरोक्त नमूना के साथ कोई समस्या है। मान लें कि आखिरकार आपका एप्लिकेशन अपडेट हो गया है। आपका ऑब्जेक्ट मॉडल काफी बदल सकता है और इसलिए इसे deserialized नहीं मिल सका। कुछ चीजें हैं जो आप यह सुनिश्चित करने के लिए कर सकते हैं कि xml संस्करण 1 से एक deserialization संस्करण 2 में अपने ऑब्जेक्ट मॉडल के लिए deserialized किया जा सकता है, लेकिन यदि संभावना है कि आप बड़े संरचनात्मक परिवर्तन हो सकता है xml deserialization जाने का रास्ता नहीं है।

यदि यह मामला है और आपका एप्लिकेशन ग्राहकों को तैनात किया गया है, तो मैं दृढ़ता से सुझाव देता हूं कि आप अपने सेव/लोड लॉजिक पर और नज़र डालें।

Versionized क्रमबद्धता/Deserialization
के रूप में अपनी वस्तु राज्य को क्रमानुसार:

<ObjectState version="1"> 
    <Field1>value</Field1> 
    ... etc ... 
</ObjectState> 

तो अब आप ऑब्जेक्ट मॉडल है कि बचाया राज्य उत्पन्न की संस्करण है। आपके deserialization में आप इस तथ्य के लिए समायोजित करने के लिए विशेष माप ले सकते हैं। उदाहरण के लिए फ़ील्ड 1-वैल्यू को किसी अन्य ऑब्जेक्ट में किसी सूची में लिखें।

एक और दृष्टिकोण होगा: के रूप में (एक संस्करण विशेषता के साथ) ऊपर उल्लेख किया

Versionized क्रमबद्धता और रूपांतरण Deserialization
से पहले अपने वस्तु राज्य को क्रमानुसार।
जब संस्करण विशेषता को देखने के लिए deserializing, यदि यह संस्करण नहीं है तो आप धारावाहिक ऑब्जेक्ट स्थिति को xsl-scripts या C# कोड के साथ अपने वर्तमान संस्करण में कनवर्ट करने की अपेक्षा करते हैं। आप अपने वर्तमान परियोजना

- conversions 
    - v1-v2 
    - v2-v3 

में XSL रूपांतरण की एक सूची बचा सकता है अगर आप 3 संस्करण में वर्तमान में कर रहे हैं और संस्करण विशेषता पर अपने xml फ़ाइल नज़र लोड और अपने वर्तमान संस्करण प्राप्त करने के लिए सभी XSL स्क्रिप्ट चलाना चाहते हैं (संस्करण 3)।तो आप xsl-script v1-v2 और बाद में v2-v3 चलाएंगे।

इस मामले में आप सामान्य क्रमबद्धता और deserialization कक्षाएं हो सकती है जो पीछे की क्षमता की परवाह नहीं करनी चाहिए।

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

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