मैं एक पुस्तकालय प्रबंधन सॉफ्टवेयर बना रहा हूं। मैंने डेटाबेस के प्रबंधन को एक अलग सी # लाइब्रेरी 'DataAccessLibrary' में अलग कर दिया है। इसमें DataAccess.cs शामिल हैं:

public static event MyDelegate Event_AddBook;

    public static void InitializeDatabase()
    {
        using (SqliteConnection db = new SqliteConnection("Filename=MyBooks.db"))
        {
            db.Open();

            //Not necessary
        }
    }

    public static void AddBook(Book book)
    {
        Event_AddBook.Invoke(book);

        using (SqliteConnection db = new SqliteConnection("Filename=MyBooks.db"))
        {
            db.Open();
            //Not necessary
        }            
    }

    public static ObservableCollection<Book> GetBooks()
    {
        ObservableCollection<Book> books = new ObservableCollection<Book>();

        using (SqliteConnection db = new SqliteConnection("Filename=MyBooks.db"))
        {
            db.Open();
            //Not necessary
        }

        return books;
    }
}

जब किसी पुस्तक को डेटाबेस में जोड़ा जाता है, तो यह घटना को आमंत्रित करती है ताकि मेरी YourBooks_View कक्षा (जो पुस्तकें प्रदर्शित करती है) को सूचित किया जाता है कि एक पुस्तक जोड़ी गई है।

(नोट: पुस्तक को एक नई विंडो का उपयोग करके जोड़ा गया है।)

किसी अन्य फ़ाइल में, मैं इस तरह डेटाबेस में एक पुस्तक जोड़ता हूं:

Book b = new Book
{
    Title = title,
    Author = author,
    Publisher = publisher,
    ISBN = isbn,
    Quantity = quantity.GetValueOrDefault(),
    CoverImageLocation = CoverImageUri
};

DataAccess.AddBook(b);

इवेंट 'Event_AddBook' को YourBooks क्लास ने सब्सक्राइब किया है:

public sealed partial class YourBooks_View : Page
{
    private BooksViewModel ViewModel { get; set; } = new BooksViewModel();

    public YourBooks_View()
    {
        this.InitializeComponent();
        DataAccess.Event_AddBook += new MyDelegate(this.GridView_AddBook);
    }

    private void GridView_AddBook(Book book)
    {
        ViewModel.Books.Add(book);
    }
}

कोड त्रुटियों के बिना संकलित करता है लेकिन रन टाइम पर, जब मैं पुस्तक जोड़ता हूं, तो यह अपवाद YourBooks_View.GridView_AddBook() लाइन पर फेंक दिया जाता है:

System.InvalidCastException एच परिणाम = 0x80004002 संदेश = 'System.Collections.Specialized.NotifyCollectionChangedEventHandler' प्रकार के COM ऑब्जेक्ट को 'System.Collections.Specialized.NotifyCollectionChangedEventHandler' टाइप करने में असमर्थ। COM घटकों का प्रतिनिधित्व करने वाले प्रकारों के उदाहरणों को उन प्रकारों में नहीं डाला जा सकता है जो COM घटकों का प्रतिनिधित्व नहीं करते हैं; हालांकि, जब तक अंतर्निहित COM घटक इंटरफ़ेस के IID के लिए QueryInterface कॉल का समर्थन करता है, तब तक उन्हें इंटरफेस में डाला जा सकता है। स्रोत = सिस्टम। निजी। कोरलिब स्टैक ट्रेस: System.StubHelpers.StubHelpers.GetCOMIPFromRCW_WinRTDelegate पर (ऑब्जेक्ट objSrc, IntPtr pCPCMD, IntPtr और ppTarget) System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke पर (ऑब्जेक्ट प्रेषक, NotifyCollectionChangedEventArgs e) System.Collections.ObjectModel.ObservableCollection1.OnCollectionChanged(NotifyCollectionChangedEventArgs e) पर System.Collections.ObjectModel.ObservableCollection पर 1.InsertItem(Int32 index, T item) System.Collections.ObjectModel.Collection`1 पर। जोड़ें (टी आइटम) Bookshelf.YourBooks_View.GridView_AddBook(Book Book) में C:\Users\Hemil\source\repos\Bookshelf\Bookshelf\YourBooks_View.xaml.cs:line 54 पर C:\Users\Hemil\source\repos\Bookshelf\DataAccessLibrary\DataAccess.cs:line 44 में DataAccessLibrary.DataAccess.AddBook(Book Book) पर Bookshelf.NewBook_View.d__3.MoveNext() पर C:\Users\Hemil\source\repos\Bookshelf\Bookshelf\NewBook_View.xaml.cs:line 137 पर

मुझे नहीं पता इसका क्या मतलब है। क्या इस समस्या को हल करने का कोई तरीका है या किसी अन्य तरीके से दृश्य को सूचित करने का कोई तरीका है।

मैं सी # में इतना अच्छा नहीं हूँ। किसी भी गलती या मूर्खतापूर्ण प्रश्न के लिए मुझे क्षमा करें।

संपादित करें: मैं Microsoft.Data.Sqlite कंटेनर में दिए गए अनुसार स्क्लाइट डेटाबेस का उपयोग कर रहा हूं।

संपादित करें: मैंने इस ट्यूटोरियल का अनुसरण किया: https://docs.microsoft.com/en-us/windows/uwp/data-access/sqlite-databases. मैं नवीनतम विंडोज 10 को लक्षित कर रहा हूं इसलिए मैंने अपने ऐप के साथ स्क्लाइट को शामिल नहीं किया

संपादित करें: मैंने संपूर्ण स्रोत कोड gitlab पर एक सार्वजनिक रिपॉजिटरी में यहां अपलोड किया है: https:/ /gitlab.com/rahem027/bookshelf2

संपादित करें: मुझे लगता है कि मुझे BookViewModel स्रोत कोड भी शामिल करना चाहिए था। खैर, यहाँ यह है:

public class BooksViewModel
{
    private ObservableCollection<Book> books { get; set; }

    public ObservableCollection<Book> Books
    {
        get { return this.books; }

        set
        {
            this.books = value;
        }
    }


    public BooksViewModel()
    {
        books = DataAccess.GetBooks();
    }
}
3
Hemil 26 सितंबर 2018, 17:33

2 जवाब

सबसे बढ़िया उत्तर

आपको यह समस्या मिलने का कारण यह है कि आप मुख्य दृश्य के ViewModel को नए दृश्य के थ्रेड से अपडेट करते हैं। जब आपने Add बटन पर क्लिक किया, तो AddBook ईवेंट ट्रिगर हो गया, यह न्यू व्यू के थ्रेड पर है, लेकिन आप YourBooks_View क्लास में मेन व्यू के ViewModel को अपडेट करते हैं। आपको उपयोग करना चाहिए > नए दृश्य के लिए UI थ्रेड पर कार्य शेड्यूल करने की विधि।

तो बस अपनी GridView_AddBook विधि के कोड को CoreDispatcher.RunAsync नई Book ऑब्जेक्ट जोड़ने के लिए UI थ्रेड पर कार्य शेड्यूल करने की विधि।

यहाँ GridView_AddBook विधि का संशोधित कोड दिया गया है:

private async void GridView_AddBook(Book book)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        ViewModel.Books.Add(book);
    });
}
3
Breeze Liu - MSFT 27 सितंबर 2018, 09:34

जिस पुस्तक वस्तु को आप संग्रह में जोड़ने का प्रयास कर रहे हैं, वह शायद डेटाबेस से जुड़ी हो, जब आप डेटाबेस के साथ कोई कार्रवाई करते हैं, तो सुनिश्चित करें कि इसका संदर्भ निपटान है (यह इस बात पर निर्भर करता है कि आप किस डीबी प्रदाता का उपयोग कर रहे हैं)।

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

private void GridView_AddBook(Book book)
{
    Book b = new Book
    {
        Title = book.title,
        Author = book.author,
        Publisher = book.publisher,
        ISBN = book.isbn,
        Quantity = book.quantity.GetValueOrDefault(),
        CoverImageLocation = book.CoverImageUri
    };
    ViewModel.Books.Add(b);
}
0
touseefbsb 26 सितंबर 2018, 17:46