2011-10-20 17 views
8

मुझे सूची सूची के पहले और अंतिम आइटम को अलग-अलग शैली में शैली की आवश्यकता है। इसे प्राप्त करने के लिए, मैंने उस उत्तर के आधार पर समाधान पर काम करना शुरू किया: Use different template for last item in a WPF itemscontrolसूची दृश्य में पहली और आखिरी वस्तु के लिए विशिष्ट आइटम टेम्पलेट

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

यह ठीक से काम करता है सिवाय इसके कि जब सूची अपडेट हो जाती है (एक आइटम जोड़ा या निकाला जाता है), टेम्पलेट्स फिर से नहीं मिलते हैं (उदाहरण के लिए, प्रारंभ में, सिंगलइटम टेम्पलेट का चयन होता है क्योंकि एक ही आइटम होता है। जब मैं जोड़ता हूं सूची में एक आइटम, कि पहले आइटम का टेम्पलेट FirstItemTemplate पर स्विच नहीं किया जाता है)। सभी वस्तुओं के लिए टेम्पलेट चयन को कैसे बल दें?

public class FirstLastTemplateSelector : DataTemplateSelector 
{ 
    public DataTemplate DefaultTemplate { get; set; } 
    public DataTemplate FirstItemTemplate { get; set; } 
    public DataTemplate LastItemTemplate { get; set; } 
    public DataTemplate SingleItemTemplate { get; set; } 

    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     ListView lv = VisualTreeHelperEx.FindParentOfType<ListView>(container); 
     if (lv != null) 
     { 
      if (lv.Items.Count == 1) 
      { 
       return SingleItemTemplate; 
      } 

      int i = lv.Items.IndexOf(item); 
      if (i == 0) 
      { 
       return FirstItemTemplate; 
      } 
      else if (i == lv.Items.Count - 1) 
      { 
       return LastItemTemplate; 
      } 
     } 
     return DefaultTemplate; 
    } 
} 

उत्तर

14

एक वैकल्पिक दृष्टिकोण के रूप में, मैं की AlternationCount बाध्यकारी सुझाव है कि अपने अपने संग्रह में आइटम्स की संख्या (जैसे Count संपत्ति) को ItemsControl। इसके बाद यह आपके ItemsControl में एक अद्वितीय AlternationIndex (0, 1, 2, ... गणना -1) में प्रत्येक कंटेनर को असाइन करेगा। अधिक जानकारी के लिए देखें: क्या आप अपने कंटेनर Style में एक DataTrigger उपयोग कर सकते हैं

http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.alternationcount.aspx

एक बार प्रत्येक कंटेनर के लिए एक अनूठा AlternationIndex है ItemTemplate सूचकांक के आधार पर स्थापित करने के लिए। यह एक कनवर्टर के साथ MultiBinding का उपयोग करके किया जा सकता है जो True देता है यदि सूचकांक गिनती के बराबर है, False अन्यथा। बेशक आप इस दृष्टिकोण के आसपास एक चयनकर्ता भी बना सकते हैं। कनवर्टर के अपवाद के साथ, यह दृष्टिकोण अच्छा है क्योंकि यह एक एक्सएएमएल केवल समाधान है।

एक उदाहरण का उपयोग करते हुए एक ListBox:

<Window x:Class="WpfApplication4.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:Collections="clr-namespace:System.Collections;assembly=mscorlib" 
     xmlns:System="clr-namespace:System;assembly=mscorlib" 
     xmlns:l="clr-namespace:WpfApplication4" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.Resources> 
      <Collections:ArrayList x:Key="MyCollection"> 
       <System:String>Item One</System:String> 
       <System:String>Item Two</System:String> 
       <System:String>Item Three</System:String> 
      </Collections:ArrayList> 

      <l:MyAlternationEqualityConverter x:Key="MyAlternationEqualityConverter" /> 

      <Style x:Key="MyListBoxItemStyle" TargetType="{x:Type ListBoxItem}"> 
       <Style.Triggers> 
        <DataTrigger Value="True"> 
         <DataTrigger.Binding> 
          <MultiBinding Converter="{StaticResource MyAlternationEqualityConverter}"> 
           <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ListBox}}" Path="Items.Count" /> 
           <Binding RelativeSource="{RelativeSource Self}" Path="(ItemsControl.AlternationIndex)" /> 
          </MultiBinding> 
         </DataTrigger.Binding> 
         <!-- Could set the ItemTemplate instead --> 
         <Setter Property="Background" Value="Red"/> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Grid.Resources> 

     <ListBox ItemsSource="{Binding Source={StaticResource MyCollection}}" 
       AlternationCount="{Binding RelativeSource={RelativeSource Self}, Path=Items.Count}" 
       ItemContainerStyle="{StaticResource MyListBoxItemStyle}" /> 
    </Grid> 

कहाँ कनवर्टर की तरह कुछ दिख सकता है:

class MyAlternationEqualityConverter : IMultiValueConverter 
{ 
    #region Implementation of IMultiValueConverter 

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (values != null && values.Length == 2 && 
      values[0] is int && values[1] is int) 
     { 
      return Equals((int) values[0], (int) values[1] + 1); 
     } 

     return DependencyProperty.UnsetValue; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 

    #endregion 
} 
+0

मैं सोच रहा हूँ तुम क्यों Datatrigger के ItemsCount लिए बाइंडिंग का उपयोग कर से तुलना नहीं की और AlternationCount के लिए मूल्य? क्या ऐसा इसलिए है क्योंकि ItemCount एक निर्भरता संपत्ति नहीं है और यह त्रुटि फेंक देगा? या कोई अन्य कारण है? क्योंकि मुझे लगता है कि यह तुलना के बराबर बूलियन होने जा रहा है और हमें कनवर्टर – CarbineCoder

+0

@ रैम्ब 00 की आवश्यकता क्यों है, मैंने इसे आज़माया और पाया: "ए 'बाइंडिंग' को 'डेटा ट्रिगर' प्रकार की 'वैल्यू' प्रॉपर्टी पर सेट नहीं किया जा सकता है" । ऐसा लगता है कि मूल्य निर्भरता नहीं है। –

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