【问题标题】:Binding complex properties in Silverlight/WPF在 Silverlight/WPF 中绑定复杂属性
【发布时间】:2010-10-16 19:25:33
【问题描述】:

假设我有一个看起来像这样的自定义数据类型:

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 解析错误。它应该如何正确显示?甚至可以以这种方式引用集合属性的特定项目吗?如果不是,我还有什么其他选择?

编辑,场景似乎不够清晰:

我有一个

IEnumberable<MyDataType>

绑定到 ItemsControl,在 DataTemplate 内我有多个 TextBox,需要引用复杂属性列表中对象的子属性。

【问题讨论】:

    标签: c# silverlight data-binding xaml silverlight-2.0


    【解决方案1】:

    我不确定你能做到这一点。通常,您会将列表绑定到列表框(或另一个“重复”控件)之类的东西上,然后其中的每个项目都将能够绑定到列表中的相关元素。

    【讨论】:

    • 我可能还不够清楚,我有一个绑定到 ItemsControl 的 IEnumerable。在我的 ItemsControl 的 DataTemplate 中,我需要引用复杂属性中特定项目的子属性。
    【解决方案2】:

    试试 {Binding ComplexProp(0).simpleSubProp}。如果这不起作用,您也可以编写一个简单的转换器来执行此操作。

    【讨论】:

    • 感谢您的回答,不幸的是,这给了我一个 System.ArgumentException“无效的绑定路径;字符”。这个转换器的外观如何?我认为转换器通常用于以特定方式格式化数据
    【解决方案3】:

    根据Path Syntax on MSDN,你可以这样做:

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

    可能是小写的“path=”给了你错误?试试“路径=”。另外,不确定这是否适用于 Silverlight...

    【讨论】:

    • 该页面用于 WPF,而不是 Silverlight。 Silverlight 不支持绑定中的索引属性。
    • 问题的标题是“Silverlight/WPF”。
    • 索引方法似乎只适用于 Silverlight 中的某些情况,不过谢谢!
    • Silverlight 3 支持绑定中的索引属性。
    【解决方案4】:

    Silverlight Indexers in property paths are broken 中的 poperty 路径索引器似乎已损坏。绕过它的方法是在帖子中建议并使用 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;
            }
        }
    }
    

    【讨论】:

      【解决方案5】:

      我一直都在做这种事情,有两种方法可以解决这个问题,具体取决于你想从中得到什么。

      如果您真的只想要列表中的一个特定成员,您可以使用转换器。 XAML 看起来像这样:

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

      不过,这通常不是我需要的,通常我需要一个控件来显示整个复杂对象,如果是这种情况,方法更像如下:

      <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 与我的业务对象匹配,因此它通常比我在代码隐藏中检查特定索引时干净得多。

      【讨论】:

        【解决方案6】:

        为了概括这一点,我建议你使用其他人提到的值转换器,并使用 ConverterParam 选项来传递索引。

        【讨论】:

          【解决方案7】:

          这在 Silverlight 4 中现在可以正常工作了。

          需要注意的是,该类有三个公共字段。将它们更改为属性(并且也是实现 INotifyPropertyChanged 的​​一个想法),然后下面的代码就可以工作了。

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

          大小写也很重要,因为绑定区分大小写。

          【讨论】:

            猜你喜欢
            • 2011-09-18
            • 1970-01-01
            • 2011-08-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多