2009-04-01 14 views
9

Diciamo che ho un tipo di dati personalizzato che sembra qualcosa di simile:rilegatura proprietà complesse in Silverlight/WPF

public class MyDataType 
{ 
    public string SimpleProp1; 
    public string SimpleProp2; 
    public List<SomeType> ComplexProp; 
} 

ora mi hava un dato controllo associato (vale a dire ItemsControl o DataGrid), che viene creato in modo dinamico. Come apparirebbe l'associazione definita nel codice xaml per accedere ad una sottoproprietà della proprietà complessa? Ho pensato che dovrebbe essere simile a questa:

<TextBox Text="{Binding simpleSubProp, path=ComplexProp[0]}" /> 

o

<TextBox Text="{Binding path=ComplexProp[0].simpleSubProp}" /> 

ma sia di quelli mi danno errori di analisi XML. Come dovrebbe apparire correttamente? È persino possibile riferirsi a un elemento specifico di una proprietà di raccolta in modo semplice? Se non lo è, quali altre opzioni ho?

EDIT, lo scenario non sembra essere sufficientemente chiaro:

ho un

IEnumberable<MyDataType> 

che è associato a un ItemsControl, all'interno del DataTemplate ho più caselle di testo che hanno bisogno di fare riferimento a sottoproprietà di un oggetto nell'Elenco della proprietà complessa.

risposta

7

Sembra che gli indicizzatori del percorso della poperty siano interrotti in Silverlight Indexers in property paths are broken. Il modo per aggirarlo è come suggerito nel post e utilizzare un IValueConverter.

XAML

<UserControl x:Class="Silverlight.Mine.Page" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:sys="System" 
    xmlns:sm="clr-namespace:Silverlight.Mine;assembly=Silverlight.Mine" 
    Width="400" Height="300"> 
    <UserControl.Resources> 
     <sm:SomeTypeConverter x:Key="MySomeTypeConverter" /> 
    </UserControl.Resources>  
    <Grid x:Name="LayoutRoot" Background="White"> 
     <TextBlock x:Name="myTextBlock" Text="{Binding Path=SomeDates, Converter={StaticResource MySomeTypeConverter}}" /> 
    </Grid> 
</UserControl> 

C# Page.xaml.cs

namespace Silverlight.Mine 
{ 
    public partial class Page : UserControl 
    { 
     private SomeType m_mySomeType = new SomeType(); 

     public Page() 
     { 
      InitializeComponent(); 
      myTextBlock.DataContext = m_mySomeType; 
     } 
    } 
} 

C# SomeType.cs

namespace Silverlight.Mine 
{ 
    public class SomeType 
    { 
     public List<DateTime> SomeDates { get; set; } 

     public SomeType() 
     { 
      SomeDates = new List<DateTime>(); 
      SomeDates.Add(DateTime.Now.AddDays(-1)); 
      SomeDates.Add(DateTime.Now); 
      SomeDates.Add(DateTime.Now.AddDays(1)); 
     } 
    } 

    public class SomeTypeConverter : IValueConverter 
    { 
     public object Convert(object value, 
         Type targetType, 
         object parameter, 
         CultureInfo culture) 
     { 
      if (value != null) 
      { 
       List<DateTime> myList = (List<DateTime>)value; 
       return myList[0].ToString("dd MMM yyyy"); 
      } 
      else 
      { 
       return String.Empty; 
      } 
     } 

     public object ConvertBack(object value, 
           Type targetType, 
           object parameter, 
           CultureInfo culture) 
     { 
      if (value != null) 
      { 
       return (List<DateTime>)value; 
      } 
      return null; 
     } 
    } 
} 
+0

Farò una prova, grazie! – gsnerf

1

Non sono sicuro che tu possa farlo. Solitamente legherai una lista a qualcosa come una listbox (o un altro controllo "ripetuto") e poi ogni elemento al suo interno sarà in grado di legarsi all'elemento pertinente nella lista.

+0

Probabilmente non l'ho reso abbastanza chiaro, ho un IEnumerable associato a un ItemsControl. All'interno del DataTemplate del mio ItemsControl ho bisogno di fare riferimento alla sottoproprietà di un oggetto specifico nella proprietà complessa. – gsnerf

2

Prova {Binding ComplexProp (0) .simpleSubProp}. Se ciò non funziona, puoi scrivere un semplice convertitore per farlo anche tu.

+0

Thx per la tua risposta, purtroppo questo mi dà un System.ArgumentException "Percorso Binding non valido; carattere". Come sarebbe un convertitore per questo? Ho pensato che i convertitori sarebbero stati usati normalmente per la formulazione dei dati in un modo specifico – gsnerf

1

Secondo il Path Syntax on MSDN, si può solo fare:

<TextBox Text="{Binding ComplexProp[0].simpleSubProp}" /> 

può essere il "percorso =" minuscola che ti ha dato errori? Prova "Path =". Inoltre, non sono sicuro se questo funziona in Silverlight ...

+0

Quella pagina è per WPF, non per Silverlight. Silverlight non supporta le proprietà indicizzate nell'associazione. – mattmanser

+0

Il titolo della domanda dice "Silverlight/WPF". –

+0

Il metodo di indicizzazione sembra funzionare solo in alcuni casi in silverlight, tuttavia comunque! – gsnerf

4

faccio questo genere di cose tutto il tempo, ci sono due modi Vorrei affrontare questo problema a seconda di ciò che vuoi da esso.

Se si desidera solo un membro specifico dell'elenco, è possibile utilizzare un convertitore.Il XAML sarebbe simile a questa:

<TextBox Text="{Binding MyDataTypeInstance, Converter={StatacResources SpecificInstanceConverter}}" /> 

che non è di solito quello che mi serve, però, di solito ho bisogno di uno di controllo per visualizzare l'intero oggetto comlex, se questo è il caso il modo per farlo è più come la seguente:

<StackPanel> 
    <Textblock Text="{Binding SimpleProp1}"/> 
    <TextBlock Text="{Bidning SimpleProp2}"/> 
    <ItemsControl ItemsSource="{Binding ComplexProp}> 
      <ItemsControl.ItemsTemplate> 
       <DataTemplate> 
        <StackPanel> 
         <TextBlock Text="{Binding ComplexPropertyName}/> 
         <InputToolkit:NumericUpDown Value="{Binding ComplexPropertyValue}/> 
        </StackPanel> 
       </DataTemplate> 
      </ItemsControl.ItemsTemplate> 
    </ItemsControl> 
</StackPanel> 

mi piace questo metodo perché la mia GUI soddisfa i miei oggetti di business, e di conseguenza di solito finisce molto più pulito di se sto controllando per gli indici specifici nel code-behind.

1

Per generalizzare fino in fondo, suggerisco di utilizzare un convertitore di valori come menzionato da altri e utilizzare l'opzione ConvertitoreParam per passare un indice.

2

Questo ora funziona bene in Silverlight 4.

Una cosa da notare, la classe ha tre campi pubblici. Cambiateli in Proprietà (e sarebbe un'idea per implementare anche INotifyPropertyChanged) e poi funziona il seguente codice.

<StackPanel> 
    <TextBlock Text="{Binding Path=SimpleProp1}" /> 
    <TextBox Text="{Binding Path=ComplexProp[0].SimpleSubProp, Mode=TwoWay}" Width="200" Height="60"/> 
</StackPanel> 

Il caso è anche importante in quanto i binding sono case-sensitive.