2012-11-13 12 views
5

का उपयोग कर व्यूमोडेल में बाध्य अवलोकन करने योग्य चयन मान्य करना मैं एमवीवीएम के लिए नया हूं, हाल ही में एमवीवीएम पैटर्न के बाद मेरी पहली परियोजना शुरू की है। मुझे IDataErrorInfo इंटरफ़ेस का उपयोग करके एक अवलोकन करने योग्य चयन को सत्यापित करने का प्रयास करने का कोई समस्या है। मेरे ObservableCollection इस तरह दिखता है:एमवीवीएम पैटर्न

ObservableCollection<Magazine> magazineRepository; 
    public ObservableCollection<Magazine> MagazineRepository 
    { 
     get { return magazineRepository; } 
     set 
     { 
      if (value != null) 
      { 
       bladRepository = value; 
       OnPropertyChanged("MagazineRepository"); 
      } 
     } 
    } 

और इस तरह मेरे XAML:

<ListBox x:Name="listMagazineRepository" 
       Grid.ColumnSpan="2" 
       ItemsSource="{Binding}" 
       DataContext="{Binding MagazineRepository}" 
       DisplayMemberPath="Navn" 
       SelectedItem="{Binding Path=SelectedItem}"/> 

     <TextBox x:Name="txtName" Grid.Row="1" Grid.Column="0" 
        Text="{Binding ElementName=listMagazineRepository, Path=SelectedItem.Navn, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> 
     <TextBox x:Name="txtPrice" Grid.Row="2" Grid.Column="0" 
        Text="{Binding ElementName=listMagazineRepository, Path=SelectedItem.Pris, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> 

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

मेरी समस्या यह है कि जब मैं अपना कोड इस तरह सेट करता हूं, तो मेरा डेटा सत्यापित करने का एकमात्र तरीका डोमेन मॉडल में है, जो वास्तव में एक अच्छा अभ्यास नहीं है, मैं चाहता हूं वहां पहुंचने से पहले ViewModel में मान्य करें। असल में मैं MagazineRepository में प्रत्येक प्रॉपर्टी को ViewModel में मान्य करना चाहता हूं, आप इसे करने के बारे में कैसे जाएंगे?

पीएस: यदि मेरे प्रश्न में जानकारी की कमी है तो मैं इस बोर्ड (और सामान्य रूप से प्रोग्रामिंग बोर्ड) पर पोस्ट करने के लिए नया हूं, कृपया मुझे बताएं और मैं आवश्यक विवरण प्रदान करूंगा।

बहुत बहुत धन्यवाद।

+0

वैसे मुझे आपके द्वारा पोस्ट किए गए कोड में एक व्यूमोडेल दिखाई नहीं देता है, लेकिन IDATErrorInfo – Alan

+0

को लागू करने के लिए आपके व्यूमोडेल के लिए सामान्य तरीका होगा क्षमा करें, मैंने सोचा कि यह निहित था।संग्रह मेरे व्यूमोडेल में है, जो वास्तव में IDataErrorInfo को लागू करता है, लेकिन जब टेक्स्टबॉक्स संग्रह में एक संपत्ति बदलता है, तो मुझे उस संपत्ति को सत्यापित करने की आवश्यकता होती है और मैं यह नहीं समझ सकता कि यह वास्तव में कैसे किया जाए। इसलिए संग्रह में किसी संपत्ति के लिए प्रत्येक 2 टेक्स्टबॉक्स हैं, और जब उस संपत्ति में परिवर्तन होता है तो मुझे उस पर सत्यापन करने की आवश्यकता होती है, जिस तरह से मैंने IDataErrorInfo के साथ सीखा है, मैं केवल पूरे संग्रह को मान्य कर सकता हूं। –

उत्तर

3

यदि मैं सही ढंग से समझता हूं तो आप पत्रिका ऑब्जेक्ट को सत्यापित करना चाहते हैं। यदि ऐसा है, तो ऐसा करने का एक तरीका है कि क्लास को व्यूमोडेल में लपेटना है, चलिए इसे मैगज़ीनवीएम कहते हैं, जो IDataErrorInfo लागू करता है और पत्रिका ऑब्जेक्ट को अपडेट करता है। फिर आप MagazineVM की एक सूची को देखने के लिए बाध्य करते हैं। एक बहुत ही सरल उदाहरण के रूप में:

public class MagazineVM : IDataErrorInfo, INotifyPropertyChanged 
{ 
    private Magazine _magazine; 

    public int FirstMagazineProperty 
    { 
     get { return _magazine.FirstMagazineProperty; } 
     set { _magazine.FirstMagazineProperty = value; RaisePropertyChanged("FirstMagazineProperty"); } 
    } 

    //INotifyPropertyChanged implementation 

    //IDataErrorInfo implementation 
} 
3

सबसे पहले, के रूप में dtex कहते हैं, आप एक MagazineViewModel वर्ग बल्कि एक पत्रिका वर्ग से उपयोग करना चाहिए। E.G.

public class MagazineViewModel : INotifyPropertyChanged, IDataErrorInfo 
{ 
    private string navn; 
    private string pris; 
    private string error; 

    public string Navn 
    { 
    get { return navn; } 
    set 
    { 
     if (navn != value) 
     { 
     navn = value; 
     RaisePropertyChanged("Navn"); 
     } 
    } 
    } 
    public string Pris 
    { 
    get { return pris; } 
    set 
    { 
     if (pris != value) 
     { 
     pris = value; 
     RaisePropertyChanged("Pris"); 
     } 
    } 
    } 
    public string Error 
    { 
    get { return error; } 
    set 
    { 
     if (error != value) 
     { 
     error = value; 
     RaisePropertyChanged("Error"); 
     } 
    } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public string this[string columnName] 
    { 
    get 
    { 
     var result = string.Empty; 

     switch (columnName) 
     { 
     case "Pris": 
      if (string.IsNullOrWhiteSpace(Pris)) 
      { 
      result = "Pris is required"; 
      } 
      break; 
     case "Navn": 
      if (string.IsNullOrWhiteSpace(Navn)) 
      { 
      result = "Navn is required"; 
      } 
      break; 
     } 

     return result; 

    } 
    } 

    private void RaisePropertyChanged(string PropertyName) 
    { 
    var e = PropertyChanged; 
    if (e != null) 
    { 
     e(this, new PropertyChangedEventArgs(PropertyName)); 
    } 
    } 

} 

ध्यान देने योग्य महत्वपूर्ण संपत्ति "सार्वजनिक स्ट्रिंग [स्ट्रिंग कॉलमनाम]" है। कॉलमनाम आपकी बाध्य संपत्तियों में से एक होगा और यह वह जगह है जहां आप सत्यापन कर सकते हैं।

विचार करने की अगली बात यह है कि आपका मेन व्यू मॉडेल (आपका डेटा कॉन्टेक्स्ट) है। E.G.

public class MainViewModel : INotifyPropertyChanged 
{ 
    //Use a readonly observable collection. If you need to reset it use the .Clear() method 
    private readonly ObservableCollection<MagazineViewModel> magazines = new ObservableCollection<MagazineViewModel>(); 

    private MagazineViewModel selectedItem; 

    //Keep the item being edited separate to the selected item 
    private MagazineViewModel itemToEdit; 

    public ObservableCollection<MagazineViewModel> Magazines { get { return magazines; } } 
    public MagazineViewModel SelectedItem 
    { 
    get { return selectedItem; } 
    set 
    { 
     if (selectedItem != value) 
     { 
     selectedItem = value; 
     RaisePropertyChanged("SelectedItem"); 
     //When the selected item changes. Copy it to the ItemToEdit 
     //This keeps the the copy you are editing separate meaning that invalid data isn't committed back to your original view model 
     //You will have to copy the changes back to your original view model at some stage) 
     ItemToEdit = Copy(SelectedItem); 
     } 
    } 
    } 
    public MagazineViewModel ItemToEdit 
    { 
    get { return itemToEdit; } 
    set 
    { 
     if (itemToEdit != value) 
     { 
     itemToEdit = value; 
     RaisePropertyChanged("ItemToEdit"); 
     } 
    } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public MainViewModel() 
    { 
    //Ctor... 
    } 

    //Create a copy of a MagazineViewModel 
    private MagazineViewModel Copy(MagazineViewModel ToCopy) 
    { 
    var vm = new MagazineViewModel(); 
    vm.Navn = ToCopy.Navn; 
    vm.Pris = ToCopy.Pris; 
    return vm; 
    } 

    private void RaisePropertyChanged(string PropertyName) 
    { 
    //... 
    } 
} 

यहां एकमात्र चीज है कि आप परिवर्तन को मूल दृश्य मॉडल में कैसे कॉपी करते हैं। आप चयनित आइटम परिवर्तनों से पहले ऐसा कर सकते हैं (यदि ItemToEdit मान्य है) या एक Commit बटन है जो केवल तब सक्षम है जब ItemToEdit मान्य है। यदि आप अपने मूल दृश्य मॉडल को अमान्य स्थिति में जाने की अनुमति दे सकते हैं तो आपको प्रतिलिपि के बारे में चिंता करने की आवश्यकता नहीं है।

अंत में XAML

एक अंतर्निहित शैली त्रुटि टूलटिप

<Style 
    TargetType="{x:Type TextBox}"> 
    <Setter 
    Property="ToolTip" 
    Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" /> 
</Style> 

और नियंत्रण और बाइंडिंग

<ListBox 
    ItemsSource="{Binding Magazines}" 
    DisplayMemberPath="Navn" 
    SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}" /> 
<TextBox 
    Margin="5" 
    x:Name="txtName" 
    Grid.Row="1" 
    Grid.Column="0" 
    Text="{Binding ItemToEdit.Navn, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> 
<TextBox 
    Margin="5" 
    x:Name="txtPrice" 
    Grid.Row="2" 
    Grid.Column="0" 
    Text="{Binding ItemToEdit.Pris, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> 

बक्सें ItemToEdit करने के लिए बाध्य दिखाने के लिए। ItemToEdit चयनित इटैम की एक इन-सिंक प्रति होगी।

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