绑定可观察集合的子项

时间:2014-10-07 14:45:13

标签: c# .net wpf data-binding observablecollection

我有以下viewmodel,我想绑定到视图:

public class EntityManagerModel
{
    public readonly ObservableCollection<EntityViewModel> m_Entities =
             new ObservableCollection<EntityViewModel>();
}
//
// implements INotifyPropertyChanged
public class EntityManagerViewModel: BaseViewModel
{
  private EntityManagerModel m_Model = new EntityManagerModel();

  public ObservableCollection<EntityViewModel> Entities
  {
      get { return m_Model.m_Entities; }
  }
}

然而,我实际想要绑定到我的视图的是EntityViewModel中包含的数据,其定义如下:

public class EntityModel
{
   public readonly PointCollection m_TrailPoints = new PointCollection();
}
//
// implements INotifyPropertyChanged
public class EntityViewModel: BaseViewModel
{
   private EntityModel m_Model = new EntityModel;

   public PointCollection TrailPoints
   {
     get { return m_Model.m_TrailPoints; }
   }
}

所以,每当我添加这样一个点时,我都希望我的观点更新:

// In some routine inside EntityManageViewModel I have this code
// this should trigger collectionChanged event:
Entities[index].TrailPoints.Add( new Point(x, y));

我的观点的XAML代码是:

<!-- EntityManagerView -->
<Grid>
    <!--Trail line-->
    <ItemsControl ItemsSource="{Binding Entities}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type vm:EntityViewModel}">
                <Polyline Stroke="Red" StrokeThickness="1">
                    <Polyline.Style>
                        <Style TargetType="{x:Type Polyline}">
                            <Setter Property="Points">
                                <Setter.Value>
                                    <MultiBinding Converter="{StaticResource pointMultiConverter}">
                                        <Binding Path="ActualWidth" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Canvas}}"/>
                                        <Binding Path="ActualHeight" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Canvas}}"/>
                                        <Binding Path="TrailPoints"/>
                                    </MultiBinding>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </Polyline.Style>
                </Polyline>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

这仅在我调整应用程序窗口大小时显示/更新行。当然,我在搜索时找到了像this这样的解决方案。但是,子类ObservableCollection在我的代码中引入了其他问题。那么,我的问题是这样做的最佳/替代方法是什么?

2 个答案:

答案 0 :(得分:1)

最简单的解决方案&#34;模拟&#34;可观察集合是将以下行添加到EntityViewModel

的构造函数中
public EntityViewModel()
{
    TrailPoints.Changed += (sender, args) => RaisePropertyChanged("TrailPoints");
}

每当更改TrailPoints集合时(例如,添加Point时),都会引发其Changed事件。我们的想法是订阅此事件并引发PropertyChanged事件以通知View有关集合已更改的信息!

答案 1 :(得分:0)

基本上,您需要挂钩父视图模型上更改的集合。

this.Entities.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(EntitiesItems_CollectionChanged);

void  EntitiesItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e){
        if (e.NewItems != null) {
            ((EntityModel)e.NewItems[0]).PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(TrailPoints_PropertyChanged);
        }
        OnPropertyChanged("Entities");

    } 

void TrailPoints_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) {
        if (e.PropertyName == "TrailPoints") {
            OnPropertyChanged("Entities");
        }

    }

当前viewModel上的INotifyPropertyChanged仅深入一级。通过挂钩集合中更改的每个属性,您可以确定如何处理集合的特定更改(添加,删除等)