2009-04-01 10 views
9

Powiedzmy mam typ danych niestandardowy, który wygląda mniej więcej tak:wiążące złożone właściwości w Silverlight/WPF

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

teraz Hava do danych związana kontroli (tj ItemsControl lub DataGrid), który jest tworzony dynamicznie. W jaki sposób powiązanie zdefiniowane w kodzie Xaml powinno mieć dostęp do podrzędności złożonej właściwości? Myślałem, że powinno to wyglądać mniej więcej tak:

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

lub

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

ale oba te dają mi xml błędy analizowania. Jak powinien wyglądać poprawnie? Czy możliwe jest nawet odwoływanie się do konkretnego elementu z kolekcji? Jeśli tak nie jest, jakie mam inne opcje?

EDIT, scenariusz nie wydaje się być wystarczająco jasne:

Mam

IEnumberable<MyDataType> 

że jest związany z ItemsControl wewnątrz DataTemplate Mam kilka pól tekstowych, które muszą odnosić się do właściwości podrzędne obiektu na liście właściwości złożonej.

Odpowiedz

7

Wygląda na to, że indeksy ścieżek poperty są uszkodzone w Silverlight Indexers in property paths are broken. Sposób obejścia tego jest zgodny z sugestią w poście i korzystaniem z 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

Dam ci spróbować, thx! – gsnerf

1

Nie jestem pewien, czy możesz to zrobić. Zazwyczaj wiążesz listę z czymś w rodzaju listbox (lub innej kontrolki "repeatating"), a następnie każdy element wewnątrz, który będzie mógł powiązać z elementem relevent na liście.

+0

Być może nie udało mi się wystarczająco jasno, mamIEnumerable związany z ItemsControl. Wewnątrz DataTemplate mojego ItemsControl muszę odwołać się do podwłasności określonego elementu w złożonej właściwości. – gsnerf

2

Spróbuj {Binding ComplexProp (0) .simpleSubProp}. Jeśli to nie zadziała, możesz napisać prosty konwerter, aby to zrobić.

+0

Thx za odpowiedź, niestety to daje mi System.ArgumentException "Nieprawidłowa ścieżka wiążąca; znak". Jak mógłby wyglądać konwerter? Myślałem, że konwertery będą normalnie używane do formowania danych w określony sposób. – gsnerf

1

Według Path Syntax on MSDN, można po prostu zrobić:

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

To może być małą "path =", który dał Ci błędy? Wypróbuj "Path =". Ponadto, nie wiesz, czy to działa w Silverlight ...

+0

Ta strona dotyczy WPF, a nie Silverlight. Silverlight nie obsługuje właściwości indeksowanych podczas wiązania. – mattmanser

+0

Tytuł pytania mówi "Silverlight/WPF". –

+0

Metoda indeksowania wydaje się działać tylko w niektórych przypadkach w silverlight, thx jednak! – gsnerf

4

robię tego typu rzeczy przez cały czas, istnieją dwa sposoby Podejdę do tego problemu w zależności od tego, co z niego chcesz.

Jeśli naprawdę chcesz tylko jednego określonego członka listy, możesz użyć konwertera.XAML będzie wyglądać mniej więcej tak:

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

To nie jest zwykle to, czego potrzebuję choć zwykle muszę jedną kontrolę, aby wyświetlić cały comlex przedmiot, jeśli to przypadek sposób na to jest bardziej jak w następujący sposób:

<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> 

lubię tę metodę, ponieważ mój GUI pasuje moje obiektów biznesowych, iw rezultacie to zazwyczaj kończy się o wiele czystsze niż jakbym sprawdzania poszczególnych indeksów w kodzie opóźnieniem.

1

Aby uogólnić to do końca, sugeruję użycie konwertera wartości wymienionego przez innych i użycie opcji ConverterParam do przekazania indeksu.

2

ta działa obecnie ok Silverlight 4.

Jedną rzeczą, aby pamiętać, klasa składa się z trzech pól publicznych. Zmień je na Właściwości (i będzie to również pomysł wdrożenia INotifyPropertyChanged), a następnie działa poniższy kod.

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

Sprawa jest również ważna, ponieważ powiązania uwzględniają duże i małe litery.