C# 在 Silverlight/WPF 中绑定复杂属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/704456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Binding complex properties in Silverlight/WPF
提问by gsnerf
Lets say I have a custom data type that looks something like this:
假设我有一个看起来像这样的自定义数据类型:
public class MyDataType
{
public string SimpleProp1;
public string SimpleProp2;
public List<SomeType> ComplexProp;
}
now I hava a data bound control (i.e. ItemsControl or DataGrid), that is created dynamically. How would the binding defined in xaml code look like to acces a subproperty of the complex property? I thought it should look something like this:
现在我有一个动态创建的数据绑定控件(即 ItemsControl 或 DataGrid)。xaml 代码中定义的绑定如何访问复杂属性的子属性?我认为它应该是这样的:
<TextBox Text="{Binding simpleSubProp, path=ComplexProp[0]}" />
or
或者
<TextBox Text="{Binding path=ComplexProp[0].simpleSubProp}" />
but both of those give me xml parse errors. How should it look correctly? Is it even possible to refer to a specific item of a collection property in souch a way? If it is not, what other options do I have?
但是这两个都给了我 xml 解析错误。它应该如何正确显示?甚至有可能以某种方式引用集合属性的特定项目吗?如果不是,我还有什么其他选择?
EDIT, The scenario doesn't seem to be clear enough:
编辑,场景似乎不够清楚:
I have an
我有一个
IEnumberable<MyDataType>
that is bound to an ItemsControl, inside the DataTemplate I have multiple TextBoxes that need to refer to subproperties of an object in the List of the complex property.
绑定到 ItemsControl,在 DataTemplate 内,我有多个 TextBox,它们需要引用复杂属性列表中对象的子属性。
采纳答案by sipwiz
Looks like poperty path indexers are broken in Silverlight Indexers in property paths are broken. The way to get around it is as suggested in the post and to use an IValueConverter.
看起来像属性路径中的属性路径中的属性路径索引器中的poperty 路径索引器已损坏。解决它的方法如帖子中所建议并使用 IValueConverter。
XAML
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
C#页面.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
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;
}
}
}
回答by Steven Robbins
I'm not sure you can do that. Usually you will bind a list to something like a listbox (or another "repeating" control) and then each item inside that will be able to bind to the relevent element in the list.
我不确定你能做到这一点。通常,您会将列表绑定到列表框(或另一个“重复”控件)之类的东西,然后其中的每个项目都将能够绑定到列表中的相关元素。
回答by Shawn Wildermuth
Try {Binding ComplexProp(0).simpleSubProp}. If that doesn't work, you can write a simple Converter to do this too.
试试 {Binding ComplexProp(0).simpleSubProp}。如果这不起作用,您也可以编写一个简单的转换器来执行此操作。
回答by Kent Boogaart
According to the Path Syntax on MSDN, you can just do:
根据MSDN上的Path Syntax,您可以执行以下操作:
<TextBox Text="{Binding ComplexProp[0].simpleSubProp}" />
It may be the lowercase "path=" that gave you errors? Try "Path=". Also, not sure if this works in Silverlight...
可能是小写的“path=”给了你错误?试试“路径=”。另外,不确定这是否适用于 Silverlight ......
回答by Eric
I do this kind of thing all the time, there are two ways I would approach this problem depending on what you want out of it.
我一直在做这种事情,有两种方法可以解决这个问题,这取决于你想从中得到什么。
If you really want only the one specific member of the list, you can use a converter. The XAML would look something like this:
如果您真的只想要列表中的一个特定成员,则可以使用转换器。XAML 看起来像这样:
<TextBox Text="{Binding MyDataTypeInstance, Converter={StatacResources SpecificInstanceConverter}}" />
That's not usually what I need though, usually I need one control to display the whole comlex object, if that's the case the way to do it is more like as follows:
不过,这通常不是我所需要的,通常我需要一个控件来显示整个复杂对象,如果是这样的话,这样做的方法更像是如下:
<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>
I like this method because my GUI matches my business objects, and as a result it usually ends up a lot cleaner than if I'm checking for specific indexes in code-behind.
我喜欢这种方法,因为我的 GUI 与我的业务对象相匹配,因此它通常比我检查代码隐藏中的特定索引要干净得多。
回答by Peter Wone
To generalise this all the way, I suggest you use a value converter as mentioned by others, and use the ConverterParam option to pass an index.
为了概括这一点,我建议您使用其他人提到的值转换器,并使用 ConverterParam 选项来传递索引。
回答by Stephen Price
This now works ok in Silverlight 4.
这现在在 Silverlight 4 中可以正常工作。
One thing to note, the class has three public fields. Change them to Properties (and would be an idea to implement INotifyPropertyChanged as well) and then the following code works.
需要注意的一件事是,该类具有三个公共字段。将它们更改为属性(并且也是实现 INotifyPropertyChanged 的想法),然后以下代码起作用。
<StackPanel>
<TextBlock Text="{Binding Path=SimpleProp1}" />
<TextBox Text="{Binding Path=ComplexProp[0].SimpleSubProp, Mode=TwoWay}" Width="200" Height="60"/>
</StackPanel>
Case is also important as the bindings are case sensitive.
大小写也很重要,因为绑定区分大小写。