WPF

2009-04-28 7 views
22

में एक डिक्शनरी के साथ दो मार्ग डेटा बाध्यकारी मैं WP12 में Dictionary<string, int> को ListView पर बांधना चाहता हूं। मैं इसे इस तरह से करना चाहता हूं कि ValuesDictionary में डेटा बाध्यकारी तंत्र के माध्यम से अपडेट हो जाएं। मैं Keys को सिर्फ Values को बदलना नहीं चाहता हूं। मुझे Dictionary पर नए मैपिंग जोड़ने की भी परवाह नहीं है। मैं बस मौजूदा लोगों को अपडेट करना चाहता हूं।WPF

ListView के ItemsSource के रूप में शब्दकोश को सेट करना यह पूरा नहीं करता है। यह काम नहीं करता है क्योंकि ListViewDictionary की सामग्री तक पहुंचने के लिए गणनाकर्ता का उपयोग करता है और उस गणना के तत्व अपरिवर्तनीय KeyValuePair ऑब्जेक्ट्स हैं।

मेरी वर्तमान जांच लाइन Keys संपत्ति का उपयोग करने का प्रयास करती है। मैं इसे अपने ListView की ItemsSource संपत्ति में असाइन करता हूं। यह मुझे Keys प्रदर्शित करने की अनुमति देता है लेकिन Dictionary में Values तक पहुंचने के लिए मुझे WPF के डाटाबेसिंग तंत्र के बारे में पर्याप्त जानकारी नहीं है।

मुझे यह प्रश्न मिला: Access codebehind variable in XAML लेकिन अभी भी अंतर को पुल नहीं लग रहा है।

क्या आप में से कोई भी इस दृष्टिकोण को कैसे काम करता है? क्या किसी के पास बेहतर दृष्टिकोण है?

ऐसा लगता है, जैसे एक अंतिम उपाय के रूप में, मैं एक कस्टम वस्तु का निर्माण कर सकता है और एक List जहाँ से मैं पुन: बनाने/अद्यतन में यह छड़ी मेरी Dictionary लेकिन इस से निर्मित डेटा बाइंडिंग कार्यक्षमता बल्कि नाकाम करने के लिए एक तरह से की तरह लगता है प्रभावी ढंग से इसका उपयोग करें।

+1

के अपने स्वयं के संस्करण को लागू कर सकते हैं? – Rauhotz

+0

आप इसे दो तरह से कैसे बनाने जा रहे हैं? क्या वे टेक्स्टबॉक्स में मूल्य प्रदर्शित किए जा रहे हैं? – Ray

+0

@ रे मेरे पास मेरे मूल्यों के लिए एक कस्टम संपादक है। अगर मेरे पास टेक्स्टबॉक्स के साथ एक उदाहरण था, तो मुझे यकीन है कि मैं इसे अपनी आवश्यकताओं को पूरा कर सकता हूं। –

उत्तर

17

मुझे नहीं लगता कि आप एक शब्दकोश के साथ जो करना चाहते हैं उसे करने में सक्षम होने जा रहे हैं।

  1. क्योंकि शब्दकोश INotifyPropertyChanged या INotifyCollectionChanged
  2. को लागू नहीं करता है क्योंकि यह दो तरह से बाध्यकारी की तरह आप चाहते हैं की अनुमति नहीं जा रहा है।

मुझे यकीन नहीं है कि यह आपकी आवश्यकताओं को ठीक से फिट करता है, लेकिन मैं ObservableCollection और एक कस्टम क्लास का उपयोग करूंगा।

मैं डेटा टेम्पलेट का उपयोग कर रहा हूं, यह दिखाने के लिए कि मूल्यों पर बाध्यकारी कैसे करें।

इस कार्यान्वयन कुंजी में बेशक

, नहीं किया जाता है तो आप सिर्फ एक ObservableCollection<int>

कस्टम वर्ग

public class MyCustomClass 
{ 
    public string Key { get; set; } 
    public int Value { get; set; } 
} 

सेट ItemsSource

ObservableCollection<MyCustomClass> dict = new ObservableCollection<MyCustomClass>(); 
dict.Add(new MyCustomClass{Key = "test", Value = 1}); 
dict.Add(new MyCustomClass{ Key = "test2", Value = 2 }); 
listView.ItemsSource = dict; 

XAML

<Window.Resources> 
    <DataTemplate x:Key="ValueTemplate"> 
     <TextBox Text="{Binding Value}" /> 
    </DataTemplate> 
</Window.Resources> 
<ListView Name="listView"> 
    <ListView.View> 
     <GridView> 
      <GridViewColumn CellTemplate="{StaticResource ValueTemplate}"/> 
     </GridView> 
    </ListView.View> 
</ListView> 
इस्तेमाल कर सकते हैं
+1

मैं वास्तव में सूची दृश्य में शब्दकोश से परिवर्तनों को प्रचारित करने के बारे में कम चिंतित हूं, क्योंकि मैं सूची दृश्य से शब्दकोश में परिवर्तन का प्रचार करने के बारे में हूं। INotify इंटरफेस लगता है जैसे वे ज्यादातर पूर्व के साथ चिंतित हैं। –

+0

हाँ, यह सही है। हालांकि मैंने एक शब्दकोश को सही ढंग से बाध्य करने की कोशिश की और इसे काम नहीं कर सका, जैसा कि आप नहीं कर सके। देखेंगे कि किसी और के पास कोई सुझाव है या नहीं। – Ray

+0

MyCustomClass को लागू करने की आवश्यकता है IotifyPropertyChanged – MikeT

6

यह थोड़ा हैकी है, लेकिन मुझे यह काम करने के लिए मिला (यह मानते हुए कि मैं समझता हूं कि आप क्या चाहते हैं)।

class ViewModel : INotifyPropertyChanged 
{ 
    public ViewModel() 
    { 
     this.data.Add(1, "One"); 
     this.data.Add(2, "Two"); 
     this.data.Add(3, "Three"); 
    } 

    Dictionary<int, string> data = new Dictionary<int, string>(); 
    public IDictionary<int, string> Data 
    { 
     get { return this.data; } 
    } 

    private KeyValuePair<int, string>? selectedKey = null; 
    public KeyValuePair<int, string>? SelectedKey 
    { 
     get { return this.selectedKey; } 
     set 
     { 
      this.selectedKey = value; 
      this.OnPropertyChanged("SelectedKey"); 
      this.OnPropertyChanged("SelectedValue"); 
     } 
    } 

    public string SelectedValue 
    { 
     get 
     { 
      if(null == this.SelectedKey) 
      { 
       return string.Empty; 
      } 

      return this.data[this.SelectedKey.Value.Key]; 
     } 
     set 
     { 
      this.data[this.SelectedKey.Value.Key] = value; 
      this.OnPropertyChanged("SelectedValue"); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void OnPropertyChanged(string propName) 
    { 
     var eh = this.PropertyChanged; 
     if(null != eh) 
     { 
      eh(this, new PropertyChangedEventArgs(propName)); 
     } 
    } 
} 

और फिर XAML में:

<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition /> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 
     <ListBox x:Name="ItemsListBox" Grid.Row="0" 
      ItemsSource="{Binding Path=Data}" 
      DisplayMemberPath="Key" 
      SelectedItem="{Binding Path=SelectedKey}"> 
     </ListBox> 
     <TextBox Grid.Row="1" 
      Text="{Binding Path=SelectedValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> 
    </Grid> 
</Window> 

Data संपत्ति के मूल्य ListBox की ItemsSource के लिए बाध्य है

मैं पहली बार एक दृश्य मॉडल वर्ग बनाया। जैसा कि आप प्रश्न में बताते हैं, इसके परिणामस्वरूप KeyValuePair<int, string> के उदाहरणों का उपयोग ListBox के पीछे डेटा के रूप में किया जाता है। मैंने DisplayMemberPath को Key पर सेट किया है ताकि कुंजी का मान ListBox में प्रत्येक आइटम के प्रदर्शित मूल्य के रूप में उपयोग किया जाएगा।

आप पाया के रूप में, तुम सिर्फ TextBox के लिए डेटा के रूप में KeyValuePair की Value, उपयोग नहीं कर सकते क्योंकि यह है कि केवल पढ़ा जाता है। इसके बजाय, TextBox दृश्य मॉडल पर एक संपत्ति के लिए बाध्य है जो वर्तमान में चयनित कुंजी के लिए मान प्राप्त कर सकता है और सेट कर सकता है (जिसे SelectedItemListBox की दृश्य मॉडल पर किसी अन्य प्रॉपर्टी पर बाध्यकारी द्वारा अपडेट किया गया है)। मुझे यह संपत्ति बेकार करनी थी (क्योंकि KeyValuePair एक संरचना है), ताकि जब कोई चयन न हो तो कोड पता लगा सके।

मेरे परीक्षण ऐप में, ऐसा लगता है कि TextBox पर दृश्य मॉडल में Dictionary पर प्रचार करने के परिणामस्वरूप दिखाई देता है।

क्या आप कम या ज्यादा क्या कर रहे हैं? ऐसा लगता है कि यह थोड़ा क्लीनर होना चाहिए, लेकिन मुझे यकीन नहीं है कि ऐसा करने का कोई तरीका है या नहीं।

+0

मेरी स्थिति थोड़ा अलग है।मैं लेबल और टेक्स्टबॉक्स के कई जोड़े के रूप में शब्दकोश <स्ट्रिंग, फ्लोट> आइटम दिखाना चाहता हूं। क्या तुम्हारे पास कोई विचार है? – YukiSakura

+0

@YukiSakura मैं शब्दकोश में पाया गया आइटम्स कंट्रोल से शुरू करूंगा, और आइटम टेम्पलेट को लेबल और टेक्स्टबॉक्स को उचित गुणों के साथ सेट करने के लिए सेट करूँगा। – Andy

+0

मैंने कोशिश की, लेकिन रनटाइम में त्रुटि हुई कि 'रीडोनली कीवैल्यूपेयर के लिए दोवे का उपयोग नहीं कर सकता ...' – YukiSakura

0

Dictionary<string, int> 

के बजाय

, आप एक

Dictionary<string, IntWrapperClass>? 

Have IntWrapperClass लागू INotifyPropertyChanged हो सकता है। फिर आप शब्दकोश में वस्तुओं के लिए एक सूचीदृश्य/सूची बॉक्स दो-तरफा बांध सकते हैं।

0

बस उपरोक्त से प्राप्त किए गए पोस्ट को पोस्ट करना। आप नीचे ObservableCollection<ObservableKvp<MyKeyObject, MyValueObject>>

कुंजी को केवल पढ़ने के लिए बनाया जा सकता है क्योंकि वे शायद कुंजी को बदला नहीं जाना चाहिए। यह प्रिज्म की जरूरत है काम करने के लिए - या आप इसे बेहतर WPF के साथ एक ObservableDictionary की तरह कुछ का उपयोग नहीं होगा INotifyPropertyChanged बजाय

public class ObservableKvp<K, V> : BindableBase 
{ 
    public K Key { get; } 

    private V _value; 
    public V Value 
    { 
     get { return _value; } 
     set { SetProperty(ref _value, value); } 
    } 

    public ObservableKvp(K key, V value) 
    { 
     Key = key; 
     Value = value; 
    } 
} 
संबंधित मुद्दे