2013-08-07 4 views
7

को ट्रिगर नहीं करता है मुझे किसी विशेष xaml डेटाबेस के साथ कोई समस्या है। मेरे पास दो सूची बॉक्स हैं (मास्टर-विवरण, इसलिए सूची बॉक्स में IsSynchronizedWithCurrentItem सत्य पर सेट है)। मैं अपने viewmodel वर्ग पर किसी पूर्णांक संपत्ति बनाई (यानी हम इस संपत्ति SelInd कॉल कर सकते हैं) और के बारे में विवरण ViewModel मैं इस तरह से बाँध:OneWayToSource बाध्यकारी के साथ चयनित इंडेक्स

SelectedIndex="{Binding Mode=OneWayToSource, Path=SelInd}" 
मैं अपने viewmodel जब विवरण लिस्टबॉक्स परिवर्तन पर चयनित आइटम जानना चाहता हूँ

मुझे रनटाइम पर कोई त्रुटि/अपवाद नहीं मिलता है, लेकिन बाध्यकारी ट्रिगर नहीं करता है: चयनित आइटम बदलते समय मेरी व्यूमोडेल की संपत्ति अपडेट नहीं होती है। यदि मैं बाइंडिंग मोड को दोवे में बदलता हूं तो सबकुछ ठीक काम करता है, लेकिन मुझे इसकी आवश्यकता नहीं है। मुझे OneWayToSource के साथ काम करने की आवश्यकता है (btw वही गैर-कामकाजी व्यवहार लागू होता है यदि मैं चयनित वैल्यू गुणों में चयनित इटैम को बांधता हूं)।

क्यों उन बाइंडिंग OneWayToSource के साथ ट्रिगर नहीं करते हैं?

चीजों को स्पष्ट करने के लिए यहां एक और पूर्ण कोड उदाहरण है: संपादित करें: मैं असली कोड (एनडीए) नहीं दिखा सकता लेकिन मैं यहां कुछ सरल और समान दिखाऊंगा (पृष्ठ का डेटाकॉन्टेक्स्ट एक उदाहरण है PageViewModel क्लास के बाद में समझाया गया) मुझे बस इतना चाहिए कि मेरी व्यूमोडेल क्लास की सेलिंड संपत्ति को दूसरी सूची बॉक्स में चयनित इंडेक्स के मान को हमेशा प्रतिबिंबित करना चाहिए। मुझे ऐसा करने के लिए वैकल्पिक तरीके मिल गए हैं (कोड हैंडलर कोड-बैक या एक संलग्न व्यवहार में) लेकिन अभी मैं उत्सुक हूं कि यह OneWayToSource बाइंडिंग के साथ क्यों काम नहीं करता है।

<Page> 
    <ContentControl x:Name="MainDataContext"> 
     <Grid DataContext={Binding Path=Masters}> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*" /> 
       <ColumnDefinition Width="*" /> 

      </Grid.ColumnDefinitions> 

      <ListBox Grid.Column="0" 
       SelectionMode="Single"       
      IsSynchronizedWithCurrentItem="True" 
      ItemsSource="{Binding }"> 
       <ListBox.ItemContainerStyle> 
      ... 
      </ListBox.ItemContainerStyle> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
       .... 
        </DataTemplate> 
      </ListBox.ItemTemplate> 
      </ListBox> 

      <ListBox Grid.Column="1" 
       SelectionMode="Single"       
       SelectedIndex="{Binding Mode=OneWayToSource, ElementName=MainDataContext,Path=DataContext.SelInd}" 
      IsSynchronizedWithCurrentItem="True" 
      ItemsSource="{Binding Path=Details}"> 
       <ListBox.ItemContainerStyle> 
      ... 
      </ListBox.ItemContainerStyle> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
       .... 
        </DataTemplate> 
      </ListBox.ItemTemplate> 
      </ListBox> 
     </Grid> 
    </ContentControl> 
</Page> 

यहाँ दृश्य मॉडल वर्ग

public class PageViewModel{ 
    public ObservableCollection<MasterClass> Masters {get;set;} 

    public int SelInd {get;set;} 

    .... 
} 

का चित्र है और यहाँ MasterClass है, यह सिर्फ एक नाम और विवरण की एक सूची

public class MasterClass{ 
    public ObservableCollection<DetailsClass> Details {get;set;} 

    public String MasterName {get;set;} 

    .... 
} 
+1

कोशिश (updateSourceTriger = PropertyChanged) अपने बंधन में भाग जानना चाहते हैं .. होप आप पहले से ही लागू कर चुके हैं inotifypropertyChnahged..on you viewmodel .. – loop

+0

धन्यवाद tanuj_loop। मैं इस सवाल में इसका उल्लेख करना भूल गया: मैंने पहले से ही अद्यतन स्रोत स्रोत का उपयोग करने का प्रयास किया है, लेकिन कुछ भी नहीं बदला है। वैसे भी, मेरा व्यूमोडेल पहले से ही INotifyProperty लागू करता है लेकिन मुझे लगता है कि यह केवल तब उपयोगी होता है जब आपको यूआई को व्यूमोडेल परिवर्तनों के बारे में सूचित करने की आवश्यकता होती है, न कि दूसरी तरफ। – Gufino2

+0

MainDataContext क्या है? अपने व्यूमोडेल कोड और एक्सएमएल पूर्ण कोड को अपडेट करें..और वास्तव में आप क्या हासिल करना चाहते हैं .. – loop

उत्तर

4

मैं अपने मामले में लगता है कि रखती है, आप मोड OneWay मोड का उपयोग करना चाहिए। डिफ़ॉल्ट रूप से, आपने मोड TwoWay का उपयोग किया है।

MSDN से उद्धरण के बारे में TwoWay:

TwoWay भी स्रोत संपत्ति या लक्ष्य संपत्ति स्वचालित रूप से अन्य अपडेट करने के लिए करने के लिए कारण बनता है परिवर्तन बंधन। इस प्रकार का बाध्यकारी संपादन योग्य रूपों या अन्य पूर्ण-इंटरैक्टिव यूआई परिदृश्यों के लिए उपयुक्त है। अधिकांश गुण वनवे बाध्यकारी के लिए डिफ़ॉल्ट होते हैं, लेकिन कुछ निर्भरता गुण (आमतौर पर उपयोगकर्ता-संपादन योग्य नियंत्रणों के गुण जैसे टेक्स्टबॉक्स की टेक्स्ट प्रॉपर्टी और चेकबॉक्स की आईस्कैक्ड प्रॉपर्टी) डिफ़ॉल्ट रूप से टूवे बाध्यकारी में डिफ़ॉल्ट होती है। यह निर्धारित करने के लिए एक प्रोग्रामेटिक तरीका है कि एक निर्भरता संपत्ति डिफ़ॉल्ट रूप से एक तरफा या दो-तरफा बांधती है, तो GetMetadata का उपयोग करके संपत्ति की संपत्ति मेटाडेटा प्राप्त करें और फिर BindsTwoWayByDefault संपत्ति के बूलियन मान को जांचें।

मोड OneWay, कि तुम need:

Oneway लक्ष्य संपत्ति के स्रोत संपत्ति स्वचालित रूप से लक्षित संपत्ति को अद्यतन करने के लिए कारण बनता है परिवर्तन, लेकिन बदलाव के लिए बाध्य स्रोत संपत्ति वापस करने के लिए प्रचारित नहीं कर रहे हैं । इस प्रकार का बाध्यकारी उपयुक्त है यदि नियंत्रण बाध्य होना केवल पढ़ने के लिए है। उदाहरण के लिए, आप एक स्टॉक टिकर जैसे स्रोत से जुड़ सकते हैं या शायद आपकी लक्षित संपत्ति में परिवर्तन करने के लिए कोई नियंत्रण इंटरफ़ेस नहीं है, जैसे किसी तालिका के डेटा-बाउंड पृष्ठभूमि रंग।यदि लक्ष्य संपत्ति के परिवर्तनों की निगरानी करने की कोई आवश्यकता नहीं है, तो OneWay बाध्यकारी मोड का उपयोग करके दोवे बाध्यकारी मोड के ओवरहेड से बचा जाता है।

मोड OneWayToSource:

OneWayToSource Oneway बंधन की reverse है; लक्ष्य संपत्ति में परिवर्तन होने पर यह स्रोत प्रॉपर्टी को अपडेट करता है। एक उदाहरण परिदृश्य यह है कि यदि आपको केवल यूआई से स्रोत मान का पुनर्मूल्यांकन करने की आवश्यकता है।

enter image description here

ठीक है, तो मैं आपको एक उदाहरण है कि मेरे लिए काम करता दिखाएंगे:

नीचे का एक बेहतर समझ के लिए एक चित्र है। शायद यह आपके लिए उपयोगी होगा। Person, इन आंकड़ों -

XAML

<Window x:Class="SelectedIndexHelp.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:SelectedIndexHelp" 
    Title="MainWindow" Height="350" Width="525" 
    ContentRendered="Window_ContentRendered" 
    WindowStartupLocation="CenterScreen"> 

    <Window.Resources> 
     <local:SelectedIndexClass x:Key="SelectedIndexClass" /> 
    </Window.Resources> 

    <Grid DataContext="{StaticResource SelectedIndexClass}"> 
     <ListBox x:Name="MyListBox" 
       BorderThickness="1" 
       Width="200" Height="200" 
       BorderBrush="#CE5E48" 
       DisplayMemberPath="Name" 
       Background="AliceBlue" 
       SelectedIndex="{Binding MySelectedIndex, Mode=OneWayToSource}" /> 

     <Label Name="SelectedIndex" VerticalAlignment="Top" 
       Content="{Binding MySelectedIndex}" 
       ContentStringFormat="SelectedIndex: {0}" 
       Width="100" Height="30" Background="Lavender" /> 
    </Grid> 
</Window> 

Code behind

public partial class MainWindow : Window 
{ 
    public class Person 
    { 
     public string Name 
     { 
      get; 
      set; 
     } 

     public int Age 
     { 
      get; 
      set; 
     }    
    } 

    private ObservableCollection<Person> DataForListBox = new ObservableCollection<Person>(); 

    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void Window_ContentRendered(object sender, EventArgs e) 
    { 
     DataForListBox.Add(new Person() 
     { 
      Name = "Sam", 
      Age = 22, 
     }); 

     DataForListBox.Add(new Person() 
     { 
      Name = "Nick", 
      Age = 21, 
     }); 

     DataForListBox.Add(new Person() 
     { 
      Name = "Cris", 
      Age = 25, 
     }); 

     DataForListBox.Add(new Person() 
     { 
      Name = "Josh", 
      Age = 36, 
     }); 

     DataForListBox.Add(new Person() 
     { 
      Name = "Max", 
      Age = 32, 
     }); 

     DataForListBox.Add(new Person() 
     { 
      Name = "John", 
      Age = 40, 
     }); 

     MyListBox.ItemsSource = DataForListBox; 
     MyListBox.Focus(); 
    } 
} 

public class SelectedIndexClass 
{ 
    private int? mySelectedIndex = 0; 

    public int? MySelectedIndex 
    { 
     get 
     { 
      return mySelectedIndex; 
     } 

     set 
     { 
      mySelectedIndex = value; 
     } 
    } 
} 

Output

enter image description here

इस उदाहरण में, वहाँ डेटा का एक वर्ग है ListBox के लिए। और वर्ग SelectedIndexClass (DataContext) है, जो संपत्ति MySelectedIndex, जो बाध्यकारी OneWayToSource की एक पैरामीटर है शामिल हैं।

Edit: मुझे खुशी है कि आपने समस्या से पता चला है। मैं उनके उदाहरण से व्याख्या करने की कोशिश करूंगा, आप ElementName मामले के साथ क्यों काम नहीं कर रहे हैं।

तो, चलो कहते हैं कि हम इस कोड डालते हैं:

<ContentControl x:Name="MainDataContext"> 
    <Grid x:Name="MainGrid" DataContext="{StaticResource SelectedIndexClass}"> 
     <ListBox x:Name="MyListBox" 
        BorderThickness="1" 
        Width="200" Height="200" 
        BorderBrush="#CE5E48" 
        DisplayMemberPath="Name" 
        Background="AliceBlue" 
        SelectedIndex="{Binding Path=DataContext.MySelectedIndex, Mode=OneWayToSource, ElementName=MainDataContext}" /> 

     <Label Name="SelectedIndex" VerticalAlignment="Top" 
       Content="{Binding MySelectedIndex}" 
       ContentStringFormat="SelectedIndex: {0}" 
       Width="100" Height="30" Background="Lavender" /> 
    </Grid> 
</ContentControl> 

आप शायद समझ में के रूप में, यह काम नहीं करेगा।

DataContext दृश्य पेड़ के एक विशिष्ट नोड पर सेट, नीचे दिए गए सभी आइटम (दृश्य पेड़ में) इसे प्राप्त करते हैं। इसका मतलब है कि DataContextworkingGrid और दृश्य पेड़ के नीचे होगा। इसलिए, निम्नलिखित कोड काम करेगा:

<ContentControl x:Name="MainDataContext"> 
    <Grid x:Name="MainGrid" DataContext="{StaticResource SelectedIndexClass}"> 
     <ListBox x:Name="MyListBox" 
        BorderThickness="1" 
        Width="200" Height="200" 
        BorderBrush="#CE5E48" 
        DisplayMemberPath="Name" 
        Background="AliceBlue" 
        SelectedIndex="{Binding Path=DataContext.MySelectedIndex, Mode=OneWayToSource, ElementName=MainGrid}" /> 

     <Label Name="SelectedIndex" VerticalAlignment="Top" 
       Content="{Binding MySelectedIndex}" 
       ContentStringFormat="SelectedIndex: {0}" 
       Width="100" Height="30" Background="Lavender" /> 
    </Grid> 
</ContentControl> 

और यह भी, यह अगर काम करेंगे बिंदु MyListBox का नाम है। आमतौर पर, जब DataContext सेट करते हैं, तो तत्व का नाम पास हो जाता है।

+0

आपकी स्पष्टीकरण के लिए धन्यवाद, लेकिन मुझे OneWayToSource व्यवहार की आवश्यकता है: मैं चाहता हूं कि मेरा सूची बॉक्स मेरे व्यूमोडेल में संपत्ति को अपडेट करे, न कि अन्य तरीके से चारों ओर :) – Gufino2

+0

@ Gufino2: क्षमा करें, मैं सही ढंग से समझ में नहीं आता। क्या आप अपनी कक्षा का पूरा कोड उस संपत्ति के साथ दिखा सकते हैं जिसे आपने कार्यान्वित किया था? –

+0

क्षमा करें, मैं असली कोड नहीं दिखा सकता लेकिन संपत्ति सिर्फ एक मानक सी # संपत्ति है, जैसे: सार्वजनिक int myProp {get; set;} मैं बस अपने बाइंडिंग टैरेट (सूची बॉक्स नियंत्रण पर चयनित इंडेक्स प्रॉपर्टी) को अपडेट करना चाहता हूं मेरे बाध्यकारी स्रोत का मूल्य (मेरे व्यूमोडेल वर्ग पर नियमित सी # संपत्ति)। मुझे बस इतना चाहिए कि मेरा वीएम क्लास जानता है कि जब उपयोगकर्ता सूची बॉक्स से कोई तत्व चुनता है, लेकिन कोड-बैक इवेंट हैंडलर या संलग्न व्यवहार का उपयोग करना गंदे और ओवरकिल लगता है जब एक बाध्यकारी मोड है जो काम करना चाहिए :) – Gufino2

2

ठीक है, मुझे इसे काम करने का एक तरीका मिला। मैंने अभी डेटा-संदर्भ "संकेत" हटा दिया है, इसलिए मुझे अपनी बाइंडिंग में एलिमेंटनाम का उपयोग करने की आवश्यकता नहीं है, और यह काम करना शुरू कर दिया।काम कर XAML उदाहरण है:

<Page> 
    <ContentControl > 
     <Grid > 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*" /> 
       <ColumnDefinition Width="*" /> 

      </Grid.ColumnDefinitions> 

      <ListBox Grid.Column="0" 
       SelectionMode="Single"       
      IsSynchronizedWithCurrentItem="True" 
      ItemsSource="{Binding Masters }"> 
       <ListBox.ItemContainerStyle> 
      ... 
      </ListBox.ItemContainerStyle> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
       .... 
        </DataTemplate> 
      </ListBox.ItemTemplate> 
      </ListBox> 

      <ListBox Grid.Column="1" 
       SelectionMode="Single"       
       SelectedIndex="{Binding Mode=OneWayToSource, Path=SelInd}" 
      IsSynchronizedWithCurrentItem="True" 
      ItemsSource="{Binding Path=Masters/Details}"> 
       <ListBox.ItemContainerStyle> 
      ... 
      </ListBox.ItemContainerStyle> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
       .... 
        </DataTemplate> 
      </ListBox.ItemTemplate> 
      </ListBox> 
     </Grid> 
    </ContentControl> 
</Page> 

अब, यदि किसी वास्तव में जानता है ElementName बंधन का उपयोग कर काम नहीं करता है क्यों, मैं इसे :)

+0

कृपया मेरा संपादन देखें। मैंने आपके मामले का वर्णन करने की कोशिश की, और यह क्यों काम नहीं किया। –

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