2012-06-09 25 views
10

में चयनित छवियां ListView.SelectedItems के लिए कोड-बाध्यकारी क्षमता को कोड की गैर-तुच्छ राशि के साथ जोड़ने पर चर्चा करने वाली कुछ पोस्ट हैं। मेरे परिदृश्य में मुझे इसे ViewModel से सेट करने की आवश्यकता नहीं है, केवल उन पर कार्रवाई करने के लिए चयनित आइटम प्राप्त करना और यह कमांड द्वारा ट्रिगर किया गया है ताकि पुश अपडेट भी आवश्यक न हो।WPF ListView प्राप्त करना। ViewModel

क्या कोई आसान समाधान है (कोड की रेखाओं के संदर्भ में), शायद कोड-पीछे में? मैं View और ViewModel को एक-दूसरे को संदर्भित करने की आवश्यकता नहीं होने तक कोड-पीछे के साथ ठीक हूं। मुझे लगता है कि यह एक और सामान्य सवाल है: "व्यू ऑन-डिमांड से डेटा प्राप्त करने के लिए वीएम के लिए सर्वोत्तम अभ्यास", लेकिन मुझे कुछ भी नहीं मिल रहा है ...

उत्तर

23

SelectedItems प्राप्त करने के लिए केवल जब आदेश कम किया जाता है तो CommandParameter का उपयोग करें और ListView.SelectedItems में पास करें।

<ListBox x:Name="listbox" ItemsSource="{Binding StringList}" SelectionMode="Multiple"/> 
<Button Command="{Binding GetListItemsCommand}" CommandParameter="{Binding SelectedItems, ElementName=listbox}" Content="GetSelectedListBoxItems"/> 
+4

'चयनित इटम्स '(बहुवचन) डेटा बाध्यकारी का समर्थन नहीं करता है। [यह लिंक] देखें (http://stackoverflow.com/questions/803216/managing- बहु- चयन-with-mvvm) और [यह लिंक] (http://social.msdn.microsoft.com/forums/en- अमेरिका/WPF/धागा/edd335ea-e5e1-48e1-91a2-793d613f5cc3 /)। यह 'क्विक पैरामीटर' के रूप में काम नहीं करता है, मैं हमेशा 'शून्य' प्राप्त करता हूं, जबकि 'चयनित इटैम' (एकवचन) का उपयोग करना ठीक है। –

+0

@ user986080 मुझे एहसास नहीं हुआ कि 'चयनित इटम्स' बाध्यकारी का समर्थन नहीं करता था। मैंने जवाब से हटा दिया। हालांकि 'कमांड पैरामीटर' काम करता है, मैंने इसका परीक्षण किया है और चयनित वस्तुओं की सूची में सक्षम था। – evanb

+0

मेरा एक्सएएमएल उदाहरण 'लिस्टबॉक्स' दिखाता है लेकिन मैंने 'ListView' भी परीक्षण किया है और चयनित पैरामीटर कमांड पैरामीटर से प्राप्त करने में सक्षम था। – evanb

2

मुझे नहीं लगता कि यह सही है यह मानने की शर्त है कि 'देखें और देखें मॉडल को एक दूसरे को जानने की आवश्यकता नहीं है'; एमवीवीएम व्यू में हमेशा व्यूमोडेल के बारे में जानें।

मैं भी मैं कहाँ पीछे देखने के कोड में ViewModel का उपयोग और फिर कुछ डेटा (चयनित आइटम की तरह) को भरने के लिए किया था स्थिति इस तरह का भर में आ गए, इस ListView तरह 3'rd पक्ष नियंत्रण का उपयोग करते समय आवश्यक हो जाता है, डेटा ग्रिड आदि

यदि सीधे वीएम संपत्ति को बाध्यकारी करना संभव नहीं है तो मैं ListViw.SelectionChanged ईवेंट सुनूंगा और उसके बाद उस दृश्य में मेरे ViewModels चयनित इटम्स संपत्ति को अपडेट करूँगा।

अद्यतन:

देखने से वीएम पुल डेटा को सक्षम करने के लिए आप देखें संभालती है कि दृश्य-विशिष्ट कार्यक्षमता और ViewModel कि इंटरफेस के माध्यम से अपने दृश्य के संदर्भ होगा पर एक इंटरफेस को बेनकाब कर सकते हैं; इंटरफ़ेस का उपयोग करना अभी भी व्यू और व्यू मॉडेल को बड़े पैमाने पर डीकॉप्लेड रखता है लेकिन मैं सामान्य रूप से इसे पसंद नहीं करता हूं।

MVVM, providing the Association of View to ViewModel

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

+0

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

8

इस बातचीत का उपयोग कर प्राप्त किया जा सकता

  1. आप

    Microsoft.Expression.Interactions System.Windows के संदर्भ में जोड़ने की आवश्यकता होगी नीचे के रूप में चलाता है।अन्तरक्रियाशीलता

अपने XAML को xmlns नीचे जोड़े

xmlns:i="http://schemas.microsoft.com/expression//2010/interactivity" 
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 

सिर्फ अपने GridView टैग के अंदर नीचे कोड जोड़े भीतर

<GridView x:Name="GridName"> 
<i:Interaction.Triggers> 
    <i:EventTrigger EventName="SelectionChanged"> 
     <i:InvokeCommandAction Command="{Binding Datacontext.SelectionChangedCommand, ElementName=YourUserControlName}" CommandParameter="{Binding SelectedItems, ElementName=GridName}" /> 
    </i:EventTrigger> 
</i:Interaction.Triggers> 

कोड अंदर ViewModel घोषित संपत्ति नीचे

public DelegateCommand<object> SelectionChangedCommand {get;set;} 

निर्माण या ViewModel के रूप में नीचे

SelectionChangedCommand = new DelegateCommand<object> (items => { 
    var itemList = (items as ObservableCollection<object>).Cast<YourDto>().ToList(); 
} 
+0

मेरे पास समान था वैकल्पिक हल, – Mihai

2

मैं आपको विश्वास दिलाता कर सकते हैं कमान प्रारंभ: SelectedItems एक XAML CommandParameter

के रूप में वास्तव में bindable खुदाई और googling के एक बहुत बाद है, मैं अंत में एक सरल उपाय मिल गया है इस आम मुद्दे पर।

यह काम आप सभी निम्नलिखित नियम का पालन करना होगा करने के लिए:

  1. Ed Ball's suggestion के बाद ', पर आप XAML आदेश डेटा बाइंडिंग, परिभाषित CommandParameter संपत्ति कमान से पहले संपत्ति। यह एक बहुत ही समय लेने वाली बग है।

  2. सुनिश्चित करें कि आपके ICommand के CanExecute और निष्पादित तरीकों वस्तु प्रकार का एक पैरामीटर किया हुआ है। इस तरह आप को चुप अपवादों को रोक सकते हैं जो तब भी होते हैं जब डेटाबेस कमांड पैरामीटर प्रकार आपके कमांड विधि के पैरामीटर प्रकार से मेल नहीं खाता है।

    private bool OnDeleteSelectedItemsCanExecute(object SelectedItems) 
    { 
        // Your goes heres 
    } 
    
    private bool OnDeleteSelectedItemsExecute(object SelectedItems) 
    { 
        // Your goes heres 
    } 
    

उदाहरण के लिए, आप या तो सूचीदृश्य/लिस्टबॉक्स के SelectedItems संपत्ति आप के लिए ICommand तरीकों या सूचीदृश्य/लिस्टबॉक्स यह आत्म भेज सकते हैं । बढ़िया, है ना?

यह समय मैं यह पता लगाने के लिए क्या किया की भारी राशि खर्च कैसे के रूप में CanExecute पैरामीटर SelectedItems प्राप्त करने के लिए किसी को रोकता है आशा है।

0

के बाद से अन्य उत्तर में से कोई भी मुझे मदद की (का उपयोग करते हुए हमेशा null था SelectedItemsCommandParameter के रूप में), यहाँ यूनिवर्सल विंडोज प्लेटफार्म (UWP) क्षुधा के लिए एक समाधान है। यह Microsoft.Xaml.Interactivity और Microsoft.Xaml.Interactions.Core का उपयोग कर काम करता है।

यहां व्यू है:

<ListView x:Name="ItemsList"> 
    <Interactivity:Interaction.Behaviors> 
     <Core:EventTriggerBehavior EventName="SelectionChanged"> 
      <Core:InvokeCommandAction Command="{x:Bind ViewModel.SelectedItemsChanged}" /> 
     </Core:EventTriggerBehavior> 
    </Interactivity:Interaction.Behaviors> 
    <!-- content etc. --> 
</ListView> 

यहाँ ViewModel है (RelayCommand MVVM लाइट से एक वर्ग है):

private List<YourType> _selectedItems = new List<YourType>(); 

private RelayCommand<SelectionChangedEventArgs> _selectedItemsChanged; 
public RelayCommand<SelectionChangedEventArgs> SelectedItemsChanged 
{ 
    get 
    { 
     if (_selectedItemsChanged == null) 
      _selectedItemsChanged = new RelayCommand<SelectionChangedEventArgs>((selectionChangedArgs) => 
      { 
       // add a guard here to immediatelly return if you are modifying the original collection from code 

       foreach (var item in selectionChangedArgs.AddedItems) 
        _selectedItems.Add((YourType)item); 

       foreach (var item in selectionChangedArgs.RemovedItems) 
        _selectedItems.Remove((YourType)item); 
      }); 
     return _selectedItemsChanged; 
    } 
} 

खबरदार है कि आप के बाद मूल संग्रह से आइटम निकालने जा रहे हैं अगर चयन पूरा हो गया है (उपयोगकर्ता बटन दबाता है आदि), यह आपके _selectedItems सूची से आइटम भी हटा देगा! यदि आप इसे फ़ोरैच लूप में करते हैं, तो आपको InvalidOperationException मिल जाएगा। इससे बचने के लिए, बस की तरह चिह्नित जगह में एक गार्ड जोड़ें:

if (_deletingItems) 
    return; 

और फिर पद्धति जहां आप उदाहरण के लिए आइटम को हटाने में, ऐसा करते हैं:

_deletingItems = true; 
foreach (var item in _selectedItems) 
    YourOriginalCollection.Remove(item); 
_deletingItems = false; 
संबंधित मुद्दे