2011-08-10 7 views
8

के साथ WPF डेटाग्रिड मैं अपने व्यूमोडेल में डब्ल्यूपीएफ में एक डाटाग्रिड बांधने की कोशिश कर रहा हूं ताकि यह डेटाबेस में किसी भी सेल परिवर्तन को अपडेट कर सके और उपयोगकर्ता को पंक्तियों को हटाने और नई पंक्तियों को जोड़ने की अनुमति दे। मुझे इसका काम मिल गया है लेकिन एडीडी और संशोधित करने के लिए एक ELEGANT समाधान नहीं मिल रहा है। यहाँ XAMLएमवीवीएम

<DataGrid AutoGenerateColumns="false" HorizontalAlignment="Left" Margin="26,41,0,0" Name="dataGrid1" 
       ItemsSource="{Binding Path=GetAllItems}" Height="200" VerticalAlignment="Top" Width="266" > 
     <DataGrid.Columns> 
      <DataGridTextColumn Binding="{Binding Path=ItemListID}" Header="ID" Visibility="Hidden"/> 
      <DataGridTextColumn Binding="{Binding Path=ItemName}" Header="Name" Width="4*" /> 
      <DataGridCheckBoxColumn Binding="{Binding Path=IsActive}" Header="Active" Width="*" /> 
     </DataGrid.Columns> 

तो मेरे विचार मॉडल विधि

private ObservableCollection< ItemsList> getAllItems() 
{ 
    using (var context = new InspectorGeneralEntities()) 
    { 
     var query = from I in context.ItemsLists 
        select I; 

     var item = new ObservableCollection<ItemsList>(query.ToList()); 
     return item; 
    } 
} 

एक पंक्ति को हटाने या datagrid पर एक पंक्ति को संशोधित करने के डेटाबेस पर प्रवाहित नहीं होता में

है।

क) क्या अन्य बाध्यकारी i) कि इन घटनाओं की पहचान करेगा

ख XAML कोड कैसे मैं इतना है कि मैं DataContext अद्यतन कर सकते हैं दृश्य मॉडल में निकाले गए रिकॉर्ड या संशोधित आइटम पता नहीं लगा पाते में बनाने की जरूरत है अगर यह स्वचालित रूप से नहीं होगा।

उत्तर

1

बस अपने पर्यवेक्षण चयन की संग्रहChanged घटना की सदस्यता लें। इवेंट हैंडलर को NotifyCollectionChangedEventArgs वर्ग का एक उदाहरण प्राप्त होता है जिसमें पंक्तियों को जोड़ा या हटाया गया है, यह बताते हुए एक संपत्ति 'एक्शन' शामिल है। इसमें पंक्तियों की सूचियां भी शामिल हैं जिन्हें '' न्यूइटम ') जोड़ा गया है या हटा दिया गया है (' OldItems ')। इससे आपको अपने डेटाबेस को अपडेट करने के लिए पर्याप्त जानकारी मिलनी चाहिए।

आप अपनी पंक्ति में INotifyPropertyChanged लागू कर सकते हैं ViewModel (कक्षा ItemsList मुझे लगता है) और उसके बाद सदस्यता लें कि यह पता लगाने के लिए कि कोई पंक्ति गंदा है और डेटाबेस में अद्यतन करने की आवश्यकता है। इंटरफ़ेस में एक एकल ईवेंट PropertyChanged होता है जिसे जब भी कोई मान बदलता है तो आपके व्यू मॉडेल के प्रॉपर्टी सेटर्स में उठाया जाना है।

आप सही हैं NotifyCollectionChanged ईवेंट डेटाबेस में तत्काल डालने के लिए बहुत जल्दी आता है। लेकिन आप ईवेंट हैंडलर में 'सम्मिलित' के रूप में पंक्ति को ध्वजांकित कर सकते हैं और पंक्ति को पूरा करने के लिए आवश्यक अंतिम संपत्ति ईवेंट (ऊपर देखें) जैसे ही इसे सम्मिलित करते हैं।

+1

दो मुद्दे; 1) NotifyCollectionChangedAction केवल तभी आग लगेगा जब आप कोई नई पंक्ति या हटाएं और मौजूदा पंक्ति जोड़ते हैं, न कि यदि आप मौजूदा पंक्ति में किसी सेल को संशोधित करते हैं। यानी यह बताने का कोई तरीका नहीं है कि पंक्ति गंदा है या नहीं। 2) जब आप पहली बार नई पंक्ति में NotifyCollectionChangedAction टाइप करना शुरू करते हैं। आपको सभी कोशिकाओं को भरने का मौका मिलने से पहले निकाल दिया जाता है। आप डीबी में एक खाली पंक्ति नहीं जोड़ सकते हैं, खासकर अगर इस बिंदु पर शून्य फ़ील्ड हैं। तो फिर आपको अपडेट का उपयोग करना होगा..जो फिर से मैं कैप्चर करने का तरीका नहीं समझ सकता। – Josef

1

मुझे आपके प्रश्न में कोड के साथ कुछ समस्याएं दिखाई देती हैं। लेकिन डेटाबेस में एक पंक्ति को हटाने का कारण है। टॉलिस्ट() - अनिवार्य रूप से आप एक नई सूची बना रहे हैं जो क्वेरी की एक प्रति है और ग्रिड उस प्रतिलिपि के तत्वों को हटा रहा है।

आप एक ListCollectionView का उपयोग करें और एक LINQ बयान के बजाय एक फ़िल्टर उपयोग करना चाहिए।

1) एक नया WPF प्रोजेक्ट बना बुलाया ListCollectionViewTest

2) MainWindow.xaml.cs में कटौती & निम्नलिखित पेस्ट (में होना चाहिए:

तरीके से ऐसा करने के लिए दिखा नमूना दिया गया है ViewModel लेकिन मैं बहुत आलसी हूँ)

using System.Collections.Generic; 
    using System.Linq; 
    using System.Windows; 
    using System.Windows.Data; 

    namespace ListCollectionViewTest 
    { 
     /// <summary> 
     /// Interaction logic for MainWindow.xaml 
     /// </summary> 
     public partial class MainWindow : Window 
     { 
      private List<Employee> equivalentOfDatabase = new List<Employee>() 
         { 
          new Employee() { FirstName = "John", LastName = "Doe", IsWorthyOfAttention = true }, 
          new Employee() { FirstName = "Jane", LastName = "Doe", IsWorthyOfAttention = true }, 
          new Employee() { FirstName = "Mr.", LastName = "Unsignificant", IsWorthyOfAttention = false }, 
         }; 

      public ListCollectionView TestList { get; set; } 
      public MainWindow() 
      { 
       DataContext = this; 

       // This is all the magic you need ------- 
       TestList = new ListCollectionView(equivalentOfDatabase); 
       TestList.Filter = x => (x as Employee).IsWorthyOfAttention; 

       InitializeComponent(); 
      } 

      private void Button_Click(object sender, RoutedEventArgs e) 
      { 
       MessageBox.Show(equivalentOfDatabase.Aggregate("Employees are: \n\r", (acc, emp) => acc + string.Format(" - {0} {1}\n\r", emp.FirstName, emp.LastName), x => x)); 
      } 
     } 

     public class Employee 
     { 
      public string FirstName { get; set; } 
      public string LastName { get; set; } 
      public bool IsWorthyOfAttention { get; set; } 
     } 
    } 

3) MainWindow.xaml में कटौती & इस पेस्ट:

<Window x:Class="ListCollectionViewTest.MainWindow" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      Title="MainWindow" Height="350" Width="525"> 

     <StackPanel> 
      <DataGrid ItemsSource="{Binding TestList}" 
         RowHeight="22" 
         AutoGenerateColumns="True"> 
      </DataGrid> 
      <Button Content="Show All Employees in DB" Click="Button_Click" /> 
     </StackPanel>   
    </Window> 
0

आपके डेटा संदर्भ उस समय मौजूद नहीं है जब आप उदपेट करेंगे।आप 'उपयोग' कथन का उपयोग कर रहे हैं जो संदर्भ को नष्ट कर देता है। डेटा को देखने का एकमात्र कारण यह है कि आपने अपने डीबी के खिलाफ एक क्वेरी को मजबूर कर दिया है (.ToList() कथन के माध्यम से)। अपने प्रश्नों के उत्तर देने के लिए:

ए) बाध्य करने के लिए विशेष रूप से कुछ और आवश्यक नहीं है b) अपने इंस्पेक्टर GeneralEntities() संदर्भ पर SaveChanges() को कॉल करना आपके डीबी में किसी भी बदलाव को अपडेट करेगा।

0

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

private ObservableCollection<ItemGridVM> _getAllItems; 

public ObservableCollection<ItemGridVM> GetAllItems 
{ 
get 
      { 
       return _getAllItems; 
      } 
      set 
      { 
       _getAllItems = value; 
       //if u want Observable Collection to get updated on edit either 
       RaisePropertyChanged("GetAllItems"); 

      } 
} 

अब किसी भी पंक्ति पर किसी भी कार्रवाई के मामले में आदेश ItemGridVM.So को बांधता यू पंक्ति मिलती है:

public class ItemGridVM : BaseViewModel 
    { 
    private Item _item;//an instance of Item class 
     public int ItemId 
       { 
        get 
        { 
         return _item.ItemId; 
        } 
        set 
        { 
         _item.ItemId = value; 
         //if you want UI changes : raise PropertyChanged Notification and binding in UI should be Update SourceTrigger:PropertyChanged 
        } 
     } 
    //Contains Commands :UpdateItem,EditItem,DeleteItem 
} 

अब yourMainViewModel में आप के रूप में ItemGridVM का एक प्रत्यक्ष संग्रह बना सकते हैं खुला गुणों के रूप में विवरण। मैंने इसका उपयोग करके एक ही समस्या का समाधान किया। (शुद्ध एमवीवीएम)