2010-11-04 5 views
25

Say ho un po 'TextBlocks sul mio UI, qualcosa in questo modo:Legatura in WPF all'elemento di matrice specificato dal proprietà

<StackPanel Orientation="Vertical"> 
    <TextBlock Text="{Binding DessertIndex}" /> 
    <TextBlock Text="{Binding Food[2]}" /> 
    <TextBlock Text="{Binding Food[{Binding DessertIndex}]}" /> 
</StackPanel> 

e nel mio codice dietro Ho qualcosa di simile:

public partial class MainWindow : Window 
{ 
    public int DessertIndex 
    { 
     get { return 2; } 
    } 

    public object[] Food 
    { 
     get 
     { 
      return new object[]{"liver", "spam", "cake", "garlic" }; 
     } 
    } 

    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = this; 
    } 
} 

I primi due blocchi di testo vengono visualizzati correttamente, visualizzando rispettivamente 2 e "torta". Il terzo non realizza ciò che mi piacerebbe, vale a dire utilizzare la proprietà DessertIndex per indicizzare in quell'array e visualizzare anche "torta". Ho fatto un po 'di ricerche qui su SO per una domanda simile ma non l'ho trovata. In definitiva, non voglio specificare valori come 2 nel mio file .xaml e vorrei fare affidamento su una proprietà invece per l'indicizzazione in quell'array. È possibile? Se sì, cosa sto sbagliando qui?


EDIT:

Quindi quello che più da vicino ho è una situazione in cui i dati sono un elenco di questi oggetti [] e sto usando il sopra StackPanel come parte di un DataTemplate per un ListBox. Quindi l'idea, come suggerisce Mark Heath in basso, di usare una proprietà che dereferenze alla matrice non sembra funzionare come vorrei. Idee?

risposta

26

Un'altra alternativa è quella di utilizzare MultiBinding con un convertitore:

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfApplication1" 
     Title="MainWindow" Height="350" Width="525"> 
    <StackPanel Orientation="Vertical"> 
     <StackPanel.Resources> 
      <local:FoodIndexConverter x:Key="foodIndexConverter" /> 
     </StackPanel.Resources> 
     <TextBlock Text="{Binding DessertIndex}" /> 
     <TextBlock Text="{Binding Food[2]}" /> 
     <TextBlock> 
       <TextBlock.Text> 
        <MultiBinding Converter="{StaticResource foodIndexConverter}"> 
         <Binding Path="DessertIndex" /> 
         <Binding Path="Food"/> 
        </MultiBinding> 
       </TextBlock.Text> 
     </TextBlock> 
    </StackPanel> 
</Window> 

Poi nel qualcosa di code-behind, il convertitore si definisce in questo modo:

namespace WpfApplication1 
{ 
    public class FoodIndexConverter : IMultiValueConverter 
    { 
     public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      if (values == null || values.Length != 2) 
       return null; 

      int? idx = values[0] as int?; 
      object[] food = values[1] as object[]; 

      if (!idx.HasValue || food == null) 
       return null; 

      return food[idx.Value]; 
     } 

     public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 
+0

Grazie Colin - questo funziona molto bene per la mia app di prova e sospetto che funzionerà altrettanto bene nella realtà. E 'stata una buona giornata - ho imparato qualcosa di veramente interessante da parte tua. :) – itsmatt

+2

Potresti essere tentato di provare qualcosa di diverso usando un ConverterParameter per evitare la multibinding. Sfortunatamente, questo non porterà da nessuna parte, in quanto ConverterParameter non può utilizzare un'associazione poiché non è una proprietà Dependency ed è necessario utilizzare MultiBinding –

10

se si sta andando alla difficoltà di avere una proprietà DesertIndex sul DataContext, perché non una proprietà che dereferenzia la matrice alimentare con DesertIndex:

public object SelectedFood 
{ 
    get { return Food[DessertIndex]; } 
}  

public int DessertIndex 
{ 
    get { return 2; } 
} 

public object[] Food 
{ 
    get 
    { 
     return new object[]{"liver", "spam", "cake", "garlic" }; 
    } 
} 

allora è possibile associare direttamente a che:

<TextBlock Text="{Binding SelectedFood}" /> 

Questo è essenzialmente l'approccio "MVVM": rendere l'oggetto datacontext con proprietà che sono giuste per il binding.

+0

Mark, grazie per la tua risposta. Vedi la mia modifica alla domanda originale per maggiori dettagli. Essenzialmente ho a che fare con un ListBox e un elenco di questi oggetti [], quindi non so come rendere il dereferenziamento come suggerisci di lavorare in questo contesto. I dati non sono miei e devo affrontarlo così com'è. Idee? – itsmatt

+0

sì, mi sono chiesto se questo potesse essere il caso. –

Problemi correlati