2010-08-10 14 views
23

क्या आइटम इंडेक्स से आइटम आइटम के आइटम टेम्पलेट के भीतर से जुड़ने का कोई तरीका है?डब्ल्यूपीएफ - आइटम्स कंट्रोल के आइटम आइटम के भीतर से आइटम इंडेक्स से जुड़ें?

उदाहरण के लिए:

<ItemsControl ItemsSource="{Binding Path=ItemList}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding Path=ThisItemsIndex}" /> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

उत्तर

26

आप बारी पंक्ति शैलियों के किसी भी प्रकार आप इस के लिए AlternationIndex का अपहरण करने में सक्षम हो सकता का उपयोग नहीं कर रहे हैं। अपने आइटम की अधिकतम संभव गिनती से अधिक कुछ करने के लिए अपने ItemsControl पर AlternationCount सेट और उसके बाद का उपयोग

Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=(ItemsControl.AlternationIndex)}" 

संपादित करें: bradgonesurfing pointed out in comments रूप में, यह आप वर्चुअलाइजेशन उपयोग कर रहे हैं अनुशंसित नहीं है, के रूप में यह केवल सूचकांक होगा जो आइटम उत्पन्न होते हैं और पूरी सूची नहीं।

+0

धन्यवाद, यह मेरी स्थिति में ठीक काम करता है! – Rachel

+4

ऐसा मत करो। Http://stackoverflow.com/questions/6511180/wpf-itemscontrol-the-current-listitem-index-in-the-itemssource/17962582#17962582 – bradgonesurfing

+0

सहायक है, लेकिन यह 0 से शुरू होता है, जो तब तक बहुत उपयोगी नहीं होता है यूआई प्रोग्रामर के लिए डिज़ाइन किया गया है। मुझे लगता है कि ज्यादातर लोग इसे चाहते हैं कि यह 1 से शुरू हो। – Chris

1

रिकॉर्ड के लिए, इसे पूरा करने का एक और तरीका है: कस्टम कनवर्टर का उपयोग करना। थोड़ा और जटिल, लेकिन आपको AlternationCount/Index के बारे में चिंता करने की ज़रूरत नहीं है।

public sealed class ArrayWrapperConverter : IValueConverter 
{ 
    private static readonly Type ArrayWrappingHelperType = typeof(ArrayWrappingHelper<>); 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null) 
     { 
      return null; 
     } 

     Type valueType = value.GetType(); 
     if (!valueType.IsArray) 
     { 
      return DependencyProperty.UnsetValue; 
     } 

     Type elementType = valueType.GetElementType(); 
     Type specificType = ArrayWrappingHelperType.MakeGenericType(elementType); 

     IEnumerable wrappingHelper = (IEnumerable) Activator.CreateInstance(specificType, value); 
     return wrappingHelper; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

internal class ArrayWrappingHelper<TValue> : IEnumerable 
{ 
    private readonly TValue[] _array; 

    public ArrayWrappingHelper(object array) 
    { 
     _array = (TValue[]) array; 
    } 

    public IEnumerator GetEnumerator() 
    { 
     return _array.Select((item, index) => new ArrayItemWrapper<TValue>(_array, index)).GetEnumerator(); 
    } 
} 

public class ArrayItemWrapper<TValue> 
{ 
    private readonly TValue[] _array; 
    private readonly int _index; 

    public int Index 
    { 
     get { return _index; } 
    } 

    public TValue Value 
    { 
     get { return _array[_index]; } 
     set { _array[_index] = value; } 
    } 

    public ArrayItemWrapper(TValue[] array, int index) 
    { 
     _array = array; 
     _index = index; 
    } 
} 

नमूना उपयोग:

<Window x:Class="WpfArrayBinding.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:c="clr-namespace:WpfArrayBinding.Converters" 
     xmlns:s="clr-namespace:System;assembly=mscorlib" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <ResourceDictionary> 
      <c:ArrayWrapperConverter x:Key="ArrayWrapperConverter" /> 

      <x:Array Type="{x:Type s:String}" x:Key="MyArray"> 
       <s:String>Foo</s:String> 
       <s:String>Bar</s:String> 
       <s:String>Baz</s:String> 
      </x:Array> 
    </ResourceDictionary> 
    </Window.Resources> 

    <ItemsControl ItemsSource="{Binding Source={StaticResource MyArray}, Converter={StaticResource ArrayWrapperConverter}}"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate>     
       <StackPanel Orientation="Horizontal"> 
        <Label Content="{Binding Index}" /> 
        <TextBox Text="{Binding Value}" /> 
       </StackPanel> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</Window> 
+0

धन्यवाद, अगली बार जब मुझे आइटम्स इंडेक्स में आइटम इंडेक्स की ज़रूरत है तो मुझे इसे एक शॉट देना होगा :) क्या आपको इसका उपयोग करके प्रदर्शन में कोई समस्या है? – Rachel

+0

नहीं, लेकिन मैंने इसे अपेक्षाकृत छोटे सरणी के साथ ही इस्तेमाल किया। –

3

यहाँ एक विधि मैं एक संग्रह आइटम पर एक bindable सूचकांक जोड़ने के लिए प्रयोग किया जाता है। मैं मूल रूप से अपने आइटम को एक कंटेनर में लपेटता हूं जिसमें एक इंडेक्स होता है, और एक कस्टम ऑब्जर्जेबल कोलेक्शन होता है जो रैपर स्वीकार करता है।

ध्यान दें कि MoveItem ओवरराइड नहीं है, लेकिन इसे पूर्ण कार्यान्वयन के लिए होना होगा।

public class IndexedItemContainerCollection<T> : ObservableCollection<IndexedItemContainer<T>> 
{ 
    public IndexedItemContainerCollection() 
    { 

    } 

    public IndexedItemContainerCollection(IEnumerable<IndexedItemContainer<T>> collection) 
     : base(collection) 
    { 
     var index = 0; 
     foreach (var item in this) 
     { 
      item.Index = index; 
     } 
    } 

    protected override void InsertItem(int index, IndexedItemContainer<T> item) 
    { 
     item.Index = index; 
     base.InsertItem(index, item); 
     foreach (var indexedItem in this.Where(x=>x.Index > index)) 
     { 
      indexedItem.Index++; 
     } 
    } 

    protected override void RemoveItem(int index) 
    { 
     base.RemoveItem(index); 
     foreach (var indexedItem in this.Where(x => x.Index > index)) 
     { 
      indexedItem.Index--; 
     } 
    } 

} 

public class IndexedItemContainer<T> 
{ 
    public int Index { get; set; } 
    public T Item { get; set; } 
} 

मैं तो एक bindable संपत्ति मैं कैसे सूचकांक प्रदर्शित किया जाता है पर नियंत्रण है कि प्राप्त करने के लिए अपना आवरण वर्ग का विस्तार:

public class NamedIndexedItemContainer<T> : IndexedItemContainer<T> 
{ 
    public string Name 
    { 
     get { return string.Format("Item #{0}", Index + 1); } 
    } 
} 

नमूना प्रयोग

XAML:

<ComboBox ItemsSource="{Binding ItemList}"> 
     <ComboBox.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Name}" /> 
      </DataTemplate> 
     </ComboBox.ItemTemplate> 
    </ComboBox> 

कोड:

private IndexedItemContainerCollection<MyItem> _itemList; 
public IndexedItemContainerCollection<MyItem> ItemList 
{ 
    get { return _itemList; } 
    set { _itemList= value; OnPropertyChanged(); } 
} 


ItemList = new IndexedItemContainerCollection<MyItem>(); 
var newItem = new NamedIndexedItemContainer<MyItem>() { Item = new MyItem() { ... } }; 
ItemList.Add(newItem); 
बेशक

, किसी भी वास्तविक MyItem उदाहरण के साथ बंधन IndexedItemContainer के आइटम संपत्ति के माध्यम से जाना होगा।

+0

धन्यवाद। मुझे आमतौर पर 'ObservableCollection 'से विरासत पसंद नहीं है, हालांकि अगर मुझे भविष्य में ऐसा कुछ चाहिए तो मैं इसे ध्यान में रखूंगा :) – Rachel

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