您不想为行创建类类型有什么原因吗?使用 XAML 时,这将使您的生活轻松一百万倍。
为您的行创建一个类类型并使其实现INotifyPropertyChanged。一旦你的类实现了INotifyPropertyChanged,就很容易在你的视图中绑定到它。
假设您遵循 MVVM 模式。这意味着您将拥有一个视图(您使用 XAML 进行编码)和一个 ViewModel。这个视图模型将是一个实现INotifyPropertyChanged 的类。在视图的构造函数中,您将 DataContext 属性设置为 ViewModel 类的新实例。
现在是列表部分。在 ViewModel 中,创建一个 ObservableCollection<MyRow>。 ObservableCollection<T> 是一个集合类型,它也实现了INotifyPropertyChanged。或者在您的情况下,听起来您有这些项目的列表。如果这是真的,我建议用另一个自定义类封装列表。它使 MVVM 模式的绑定更加自然。您可以双重嵌套 ObservableCollection,但您必须决定它是否易于阅读和理解。例如,ObservableCollection<ObservableCollection<MyRow>>。在下面的示例中,我假设您创建了一个类 (MySet) 来保存行,而不是双嵌套列表。
自定义行类
public class MyRow : INotifyPropertyChanged
{
public event PropertyChanged;
private string _stringValue = string.Empty;
public string StringValue
{
get { return _stringValue; }
set
{
if( _stringValue != value )
{
_stringValue = value;
if( PropertyChanged != null )
{
PropertyChanged( this, new PropertyChangedEventArgs( "StringValue" ) );
}
}
}
}
// continue with the rest of your properties
}
行集类
public class MySet : INotifyPropertyChanged
{
public event PropertyChanged;
private ObservableCollection<MyRow> _rows = null;
public ObservableCollection<MyRow> Rows
{
get { return _rows; }
set
{
if( _rows != value )
{
_rows = value;
if( PropertyChanged != null )
{
PropertyChanged( this, new PropertyChangedEventArgs( "Rows" ) );
}
}
}
}
}
查看模型
public class MyViewModel : INotifyPropertyChanged
{
public event PropertyChanged;
private ObservableCollection<MySet> _rowSets = null;
public ObservableCollection<MySet> RowSets
{
get { return _rowSets; }
set
{
if( _rowSets != value )
{
_rowSets = value;
if( this.PropertyChanged != null )
{
this.PropertyChanged( this, new PropertyChangedEventArgs( "RowSets" ) );
}
}
}
}
}
现在在您的 XAML 中,您可以选择如何显示列表的嵌套性质。我推荐ItemsControl 容器。您所要做的就是将ItemsSource 设置为您的ViewModel 的属性名称,然后覆盖DataTemplate。如果这样做,那么每个项目都将具有内部列表的数据上下文。与另一个 ItemsControl 重复,然后您将让项目上下文等于每个内部项目 (MyRow)。
视图的 XAML
<ItemsControl
ItemsSource="{Binding Path=RowSets}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl
ItemsSource="{Binding Path=Rows}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock
Text="{Binding Path=StringValue, Mode=OneWay}"
Margin="5,0,0,0"
/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
并且不要忘记将视图的 DataContext 设置为 ViewModel。
查看后面的代码
public class View : UserControl
{
public View()
{
InitializeComponents();
this.DataContext = new ViewModel();
}
}
上面的代码未经测试,只是让您大致了解如何使用它。
更新
如果您不想创建类而只想绑定到数组,您也可以这样做。绑定路径允许索引器语法。您可以在 XAML 中输入Text="{Binding Path=MyArray[0]}"。
如果您有一个数组,XAML 可能如下所示:
<ItemsControl ItemsSource="{Binding Path=MyOuterArray}">
<ItemsControl.ItemTemplate>
<!-- The data context here is the inner array so the indexer are applied to the inner array -->
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=[0]}" />
<TextBlock Text="{Binding Path=[1]}" />
<TextBlock Text="{Binding Path=[2]}" />
</StackPanel>
</ItemsControl.ItemTemplate>
</ItemsControl>
其他几个选项是使用转换器将数组中的值转换为某种字符串格式,或者在负责适当格式化成员的行类上提供一个属性。您只是将数组元素打印为序列中的字符串吗?然后只需在名为“FormattedValue”的行类上创建一个自定义属性,并让它返回所有相关属性的 ToString() 连接。
public class MyRow : INotifyPropertyChanged
{
// ...
public string FormattedValue
{
get
{
return string.Join( ", ", this.MyArray );
}
}
}