主 - 细节数据绑定

时间:2014-09-21 13:27:06

标签: wpf xaml data-binding windows-8.1

我的应用程序中有两个模型:

class Line
{
    string line_id  { get; set; }
    string color { get; set; }
}

class Point 
{
    string point_id { get; set; }
    string line_id { get; set; }
    int weight { get; set; }
}

我有两个ObservableCollection:

lines - ObservableCollection<Line>
points - ObservableCollection<Point>

我想显示两个ListBox':第一个(外部)显示行,第二个(内部)显示属于到此行的点。

<ListView x:Name="lvPoint" ItemsSource="{Binding}">
  <ListView.ItemTemplate>
    <DataTemplate>
      <StackPanel>
        <TextBlock Text="{Binding color, Mode=TwoWay}" />
            <ListBox ItemsSource="{Binding SOMETHING, Mode=TwoWay}">
              <ListBox.ItemTemplate>
                <DataTemplate>
                  <StackPanel>
                    <TextBlock Text="{Binding weight, Mode=OneWay}" />                                                
                  </StackPanel>
                </DataTemplate>
              </ListBox.ItemTemplate>
           </ListBox>
       </StackPanel>
     </DataTemplate>
   </ListView.ItemTemplate>
 </ListView>

我在代码中为外部ListBox设置了DataContext:

lvPoint.DataContext = lines;

如何为内部ListBox设置DataContext以显示每行的Points?

1 个答案:

答案 0 :(得分:1)

您的Line模型对此方案不利。它应该有一个名为Points的属性,其中包含属于Line的感兴趣的点。然后Binding很简单:

class Line {
  public string line_id  { get; set; }
  public string color { get; set; }
  ObservableCollection<Point> _points;
  public ObservableCollection<Point> Points {
    get {
        if (_points == null) _points = new ObservableCollection<Point>();
        return _points;
    }
  }
}

然后在XAML代码中,您可以将Path设置为Points,如下所示:

<ListBox ItemsSource="{Binding Points, Mode=TwoWay}">
    <ListBox.ItemTemplate>
       <DataTemplate>
          <StackPanel>
            <TextBlock Text="{Binding weight, Mode=OneWay}" />                  
          </StackPanel>
       </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

上面的模型只是一个显示主要想法的例子。根据当前的项目,完整的实施当然应该是不同的和更先进的。

更新:不使用上述模型,您可以尝试Converter使用BindingBinding直接设置为当前项(Line)。 Converter会将Line转换为points(可能基于line_id和您的查询方法):

public class LineToPointsConverter : IValueConverter {
   public object Convert(object value, Type targetType, object parameter,
                         System.Globalization.CultureInfo culture){
      var line = value as Line;
      //convert to points by querying the points based on line.line_id here
      return ...
   }
   public object ConvertBack(object value, Type targetType, 
                             object parameter, 
                             System.Globalization.CultureInfo culture){
      return Binding.DoNothing;
   }                             
}

定义LineToPointsConverter的静态属性或在Resources中创建该转换器的实例:

<Window.Resources>
   <local:LineToPointsConverter x:Key="lineToPointsConverter"/>  
</Window.Resources>

然后在XAML代码中设置转换器:

<ListBox ItemsSource="{Binding Mode=TwoWay, Path=.,
                             Converter={StaticResource lineToPointsConverter}}">
    <ListBox.ItemTemplate>
       <DataTemplate>
          <StackPanel>
            <TextBlock Text="{Binding weight, Mode=OneWay}" />                  
          </StackPanel>
       </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>