2009-04-01 3 views
9

Допустим, у меня есть тип данных пользовательского, который выглядит примерно так:переплета сложные свойства в Silverlight/WPF

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

теперь я хава данных, связанный контроль (т.е. ItemsControl или DataGrid), который создается динамически. Как бы привязка, определенная в коде xaml, выглядела как доступ к подзадачу сложного свойства? Я подумал, что это должно выглядеть примерно так:

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

или

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

но оба эти дают мне XML ошибки синтаксического анализа. Как это должно выглядеть правильно? Можно ли вообще ссылаться на конкретный элемент коллекции? Если это не так, какие у меня есть другие варианты?

EDIT, сценарий не кажется, достаточно ясно:

У меня есть

IEnumberable<MyDataType> 

, привязанный к ItemsControl, внутри DataTemplate У меня есть несколько TextBoxes, которые должны относиться к под-свойства объекта в Списке сложного свойства.

ответ

7

Похоже, что индексы указателей поворота разбиты в Silverlight Indexers in property paths are broken. Способ обойти это, как было предложено на этом посту, и использовать 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

Я дам вам попробовать, thx! – gsnerf

1

Я не уверен, что вы можете это сделать. Обычно вы свяжете список с чем-то вроде списка (или другого «повторяющегося» элемента управления), а затем каждый элемент внутри него сможет привязываться к соответствующему элементу в списке.

+0

Возможно, я не сделал это достаточно ясно, у меня есть IEnumerable , связанный с ItemsControl. Внутри DataTemplate моего ItemsControl мне нужно ссылаться на подзадачу определенного элемента в сложном свойстве. – gsnerf

2

Попробуйте {Binding ComplexProp (0) .simpleSubProp}. Если это не сработает, вы можете написать простой Конвертер, чтобы сделать это тоже.

+0

Thx для вашего ответа, к сожалению, это дает мне System.ArgumentException «Invalid Binding Path; character». Как бы выглядел конвертер для этого? Я думал, что конвертеры будут нормально использоваться для форматирования данных определенным образом. – gsnerf

1

Согласно Path Syntax on MSDN, вы можете просто сделать:

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

Это может быть в нижнем регистре «путь =», который дал вам ошибки? Попробуйте «Путь =». Кроме того, не уверен, что это работает в Silverlight ...

+0

Эта страница предназначена для WPF, а не для Silverlight. Silverlight не поддерживает индексированные свойства в привязке. – mattmanser

+0

Название вопроса гласит: «Silverlight/WPF». –

+0

Метод индексирования работает только для некоторых случаев в silverlight, тем не менее! – gsnerf

4

я такого рода вещи все время, есть два пути Я бы подошел к этой проблеме в зависимости от того, что вы хотите от нее.

Если вам действительно нужен только один конкретный член списка, вы можете использовать конвертер.XAML будет выглядеть примерно так:

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

Это обычно не то, что мне нужно, хотя, как правило, мне нужно один элемент управления, чтобы отобразить весь COMLEX объект, если это так, то, как сделать это больше похоже на следующее:

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

Мне нравится этот метод, потому что мой GUI соответствует моим бизнес-объектов, и в результате он обычно заканчивается намного чище, чем если бы я проверяю для конкретных индексов кода позади.

1

Чтобы обобщить это полностью, я предлагаю вам использовать преобразователь значений, как упомянуто другими, и использовать параметр ConverterParam для передачи индекса.

2

Это теперь работает нормально в Silverlight 4.

Одна вещь, чтобы отметить, класс имеет три открытых полей. Измените их на свойства (и это будет идея для реализации INotifyPropertyChanged), а затем работает следующий код.

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

Дело также важно, поскольку привязки чувствительны к регистру.