2011-03-01 15 views
5

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

मैंने संग्रह वापस देखने के लिए इनलाइन xaml का उपयोग करके एक मूल कॉम्बो बॉक्स (डेटा टेम्पलेट के अंदर नहीं) का उपयोग करने का प्रयास किया है (सीवी को स्थिर संसाधन के रूप में बनाने के विपरीत)। मैं प्रदर्शित करने के लिए अपना डेटा सफलतापूर्वक प्राप्त करने में सक्षम नहीं हूं। मैं शायद इस बारे में पूरी तरह गलत हूं क्योंकि मैं अभी भी WPF के लिए नया हूं।

यहाँ मेरी कॉम्बो बॉक्स के लिए XAML है:

<ComboBox> 
    <ComboBox.ItemsSource> 
     <Binding> 
      <Binding.Source> 
       <CollectionViewSource Source="{Binding Path=Configurations}"> 
        <CollectionViewSource.SortDescriptions> 
         <scm:SortDescription PropertyName="AgencyName" /> 
        </CollectionViewSource.SortDescriptions> 
       </CollectionViewSource> 
      </Binding.Source> 
     </Binding> 
    </ComboBox.ItemsSource> 
</ComboBox> 

उपयोगकर्ता नियंत्रण जहां इस कॉम्बो बॉक्स रहता है एक वस्तु है जो एक ObservableCollection विन्यास कहा जाता है के लिए बाध्य है की DataContext और प्रत्येक विन्यास एक संपत्ति AgencyName कहा जाता है । मैंने सत्यापित किया है कि यह सीवी के बिना मानक बाध्यकारी का उपयोग करके ठीक काम करता है, इसलिए मुझे पता है कि उस सब कुछ ठीक है।

किसी भी मदद की बहुत सराहना की जाएगी क्योंकि मैं अपने मालिक को बहाने से बाहर चला गया हूं :)। मैं भी कोड में उतरना नहीं चाहता हूं और कोड के पीछे क्रमबद्ध करना चाहता हूं (जब मैं ऑब्जर्जेबल कोलेक्शन बना सकता हूं लेकिन आईएमएचओ जो डीआरवाई सिद्धांत का उल्लंघन करता है)।

उत्तर

3

वास्तव में क्या आप "जब भी अन्य बक्से में से एक में बदल गया था सभी दूसरों मतलब है के लिए बदल दिया प्रतिबिंबित "? क्या आप चयनित इटिम के बारे में बात कर रहे हैं? यदि ऐसा है, तो यह आपके कॉम्बोबॉक्स में IsSynchronizedWithCurrentItem = false सेटिंग करने में मदद कर सकता है।

इसके अलावा: मुझे लगता है कि जब तक आप केवल एक बार के पीछे कोड में अपना आईसीओलेक्शन व्यू बनाते हैं और क्रमबद्ध करते हैं, तो DRY सिद्धांत का कोई उल्लंघन नहीं होता है, क्योंकि अब आप XAML में और अधिक नहीं करते हैं। लेकिन मुझे लगता है कि मॉडल-व्यू-व्यू मॉडेल के संदर्भ में, सॉर्टिंग जैसी सुविधा को दृश्य में किया जाना चाहिए अन्य कारण भी हो सकते हैं।

+0

आह IsSynchronizedWithCurrentItem एक आकर्षण की तरह काम करता है। यह सूची के साथ सिंक्रनाइज़ नहीं करता है और यह ModelView पर किसी संपत्ति को बाध्यकारी नहीं रोकता है। मैंने बस इसे सत्यापित करना समाप्त कर दिया। यह लालित्य के साथ मेरी समस्या हल करता है। मैं और अधिक नहीं पूछ सकता, धन्यवाद। – SRM

+0

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

+0

पीएस। काफी विचित्र है कि यह डिफ़ॉल्ट WPF व्यवहार है, या कम से कम टेम्पलेट्स में डिफ़ॉल्ट है, लेकिन ओह ठीक है। –

1

आपकी पूरी पोस्ट नहीं पढ़ी, लेकिन समस्या यह है कि संसाधन डिफ़ॉल्ट रूप से साझा किए जाते हैं। इसलिए प्रत्येक कॉम्बो बॉक्स उसी संग्रह दृश्य का संदर्भ दे रहा था। एक संग्रह दृश्य में ट्रैकिंग चयन शामिल है, इसलिए एक कॉम्बो बॉक्स में चयन को बदलने से दूसरों को प्रभावित होगा।

के बजाय एक स्थानीय संसाधन के लिए सीवीएस ले जाते हैं, तो आप सिर्फ यह साझा किए जाने से रोका जा सकता है:

<CollectionViewSource x:Key="whatever" x:Shared="False" .../> 
+0

यह आशाजनक लग रहा है। मैं इसे एक शॉट दूंगा (क्योंकि मेरे सीवी साझा पहलू के अलावा पूरी तरह से काम कर रहे थे)। धन्यवाद! – SRM

+0

वैसे जो आशाजनक लग रहा था लेकिन यह काम नहीं कर रहा था। मैंने एक्स जोड़ा: साझा विशेषता (जो किसी कारण से इंटेलिसेंस में दिखाई नहीं दे रही थी) और कॉम्बो बॉक्स ने किसी भी सामग्री को प्रस्तुत करना बंद कर दिया था। ध्वज को सही में बदलें और सब कुछ ठीक काम करता है – SRM

0

हालांकि यह शायद बहुत देर हो चुकी है, मैं इस जवाब को उन लोगों के लिए छोड़ रहा हूं जो इस समस्या का सामना कर सकते हैं। CollectionViewSource.Source के लिए आपका बाध्यकारी काम नहीं करता है क्योंकि संग्रह दृश्य दृश्य दृश्य/तार्किक पेड़ से संबंधित नहीं है, और यह न तो डेटा संदर्भ प्राप्त करता है और न ही बाध्यकारी स्रोत के रूप में कॉम्बोबॉक्स को संदर्भित करने में सक्षम है। मैं निम्नलिखित वर्ग का उपयोग कर एक बदसूरत, लेकिन सरल तरीके से इस का समाधान करने में सक्षम था:

/// <summary> 
/// Provides a way to set binding between a control 
/// and an object which is not part of the visual tree. 
/// </summary> 
/// <remarks> 
/// A bright example when you need this class is having an 
/// <see cref="ItemsControl"/> bound to a <see cref="CollectionViewSource"/>. 
/// The tricky thing arises when you want the <see cref="CollectionViewSource.Source"/> 
/// to be bound to some property of the <see cref="ItemsControl"/> 
/// (e.g. to its data context, and to the view model). Since 
/// <see cref="CollectionViewSource"/> doesn't belong to the visual/logical tree, 
/// its not able to reference the <see cref="ItemsControl"/>. To stay in markup, 
/// you do the following: 
/// 1) Add an instance of the <see cref="BindingBridge"/> to the resources 
/// of some parent element; 
/// 2) On the <see cref="ItemsControl"/> set the <see cref="BindingBridge.BridgeInstance"/> attached property to the 
/// instance created on step 1) using <see cref="StaticResourceExtension"/>; 
/// 3) Set the <see cref="CollectionViewSource.Source"/> to a binding which has 
/// source set (via <see cref="StaticResourceExtension"/>) to <see cref="BindingBridge"/> 
/// and path set to the <see cref="BindingBridge.SourceElement"/> (which will be the control 
/// on which you set the attached property on step 2) plus the property of interest 
/// (e.g. <see cref="FrameworkElement.DataContext"/>): 
/// <code> 
/// <CollectionViewSource 
///  Source="{Binding SourceElement.DataContext.Images, Source={StaticResource ImagesBindingBridge}}"/> 
/// </code>. 
/// 
/// So the result is that when assigning the attached property on a control, the assigned 
/// <see cref="BindingBridge"/> stores the reference to the control. And that reference can be 
/// retrieved from the <see cref="BindingBridge.SourceElement"/>. 
/// </remarks> 
public sealed class BindingBridge : DependencyObject 
{ 
    #region BridgeInstance property 

    public static BindingBridge GetBridgeInstance(DependencyObject obj) 
    { 
     Contract.Requires(obj != null); 
     return (BindingBridge)obj.GetValue(BridgeInstanceProperty); 
    } 

    public static void SetBridgeInstance(DependencyObject obj, BindingBridge value) 
    { 
     Contract.Requires(obj != null); 
     obj.SetValue(BridgeInstanceProperty, value); 
    } 

    // Using a DependencyProperty as the backing store for BridgeInstance. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty BridgeInstanceProperty = 
     DependencyProperty.RegisterAttached("BridgeInstance", typeof(BindingBridge), typeof(BindingBridge), 
     new PropertyMetadata(OnBridgeInstancePropertyChanged)); 

    #endregion BridgeInstance property 

    #region SourceElement property 

    public FrameworkElement SourceElement 
    { 
     get { return (FrameworkElement)GetValue(SourceElementProperty); } 
     private set { SetValue(SourceElementPropertyKey, value); } 
    } 

    // Using a DependencyProperty as the backing store for SourceElement. This enables animation, styling, binding, etc... 
    private static readonly DependencyPropertyKey SourceElementPropertyKey = 
     DependencyProperty.RegisterReadOnly("SourceElement", typeof(FrameworkElement), typeof(BindingBridge), new PropertyMetadata(null)); 

    public static readonly DependencyProperty SourceElementProperty; 

    #endregion SourceElement property 

    /// <summary> 
    /// Initializes the <see cref="BindingBridge"/> class. 
    /// </summary> 
    static BindingBridge() 
    { 
     SourceElementProperty = SourceElementPropertyKey.DependencyProperty; 
    } 

    private static void OnBridgeInstancePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var sourceElement = (FrameworkElement)d; 
     var bridge = (BindingBridge)e.NewValue; 
     bridge.SourceElement = sourceElement; 
    } 
} 

यहाँ उपयोग का एक उदाहरण है (संसाधन शब्दकोश नहीं दिखाया गया है):

<ItemsControl 
     infrastructure:BindingBridge.BridgeInstance="{StaticResource ImagesBindingBridge}"> 
     <ItemsControl.ItemsSource> 
      <Binding> 
       <Binding.Source> 
        <CollectionViewSource 
           Source="{Binding SourceElement.DataContext.Images, Source={StaticResource ImagesBindingBridge}, Mode=OneWay}"> 
         <CollectionViewSource.SortDescriptions> 
          <componentModel:SortDescription PropertyName="Timestamp" Direction="Descending"/> 
         </CollectionViewSource.SortDescriptions> 
        </CollectionViewSource> 
       </Binding.Source> 
      </Binding> 
     </ItemsControl.ItemsSource> 
    </ItemsControl> 
0

बाध्यकारी निर्भर करता है विजुअलट्री पर जो सीवी एक दृश्य नहीं है, इसलिए बाध्यकारी काम नहीं करता है।

आप इसके बजाय x: संदर्भ का उपयोग कर सकते हैं।

<Border x:Name="border" /> 
<ComboBox> 
    <ComboBox.ItemsSource> 
     <Binding> 
      <Binding.Source> 
       <CollectionViewSource Source="{Binding Path=DataContext.Configurations, Source={x:Reference border}}"> 
        <CollectionViewSource.SortDescriptions> 
         <scm:SortDescription PropertyName="AgencyName" /> 
        </CollectionViewSource.SortDescriptions> 
       </CollectionViewSource> 
      </Binding.Source> 
     </Binding> 
    </ComboBox.ItemsSource> 
</ComboBox> 
संबंधित मुद्दे