绑定到ObservableCollection项的属性

时间:2015-01-21 14:41:27

标签: wpf observablecollection

interface ICar
{
   UserControl SmallView{ get; }
   UserControl CompleteView{ get; }
}

class ViewModel
{
   ObservableCollection<ICar> Cars{ get; set;}
   ObservableCollection<UserControl> SmallViews{ get; }
   ObservableCollection<UserControl> CompleteViews{ get; }
}

XAML
<ItemControl ItemsSource="{Binding SmallViews}"/>
<ItemControl ItemsSource="{Binding CompleteView}"/>

我正在向ViewModel.Cars集合添加ICars实例。当发生这种情况时,我希望在View(XAML)中添加两个UserControls(小和完整)。

- 我可以通过在Cars.CollectionChanged被提升时在CodeBehind中设置ItemsSource来让它按照我的意愿工作。但我担心所有的集合都会重新绘制到ItemsSource中的所有项目。我只想添加更改,我希望优雅的解决方案没有很多CodeBehind。


这个Codebehind使它按预期工作 - 但我想要一些更清洁的东西与真正的绑定。 CompleteControls和SmallControls是上面ItemControls的名称,在此解决方案中没有绑定标记:-(。

  public CarsView(ViewModel viewModel)
    {
      InitializeComponent();
      DataContext = viewModel;
      UpdateViews(viewModel.Cars);

      viewModel.Cars.CollectionChanged += (caller, args) =>
        UpdateViews(args.NewItems.Cast<ICar>());
    }

    private void UpdateViews(IEnumerable<ICar> newCars)
    {
      foreach (var car in newCars)
      {
        CompleteControls.Items.Add(car.CompleteView);
        SmallControls.Items.Add(car.SmallView);
      }
    }

1 个答案:

答案 0 :(得分:0)

我在你的概念中看到了一些缺陷。

class ViewModel
{
    ObservableCollection<ICar> Cars{ get; set;}

    // This is wrong for MVVM. You don't need this.
    //
    // ObservableCollection<UserControl> SmallViews{ get; }
    // ObservableCollection<UserControl> CompleteViews{ get; }
}

它也将摆脱这一点。

  UpdateViews(viewModel.Cars);
  viewModel.Cars.CollectionChanged += (caller, args) =>
    UpdateViews(args.NewItems.Cast<ICar>());

关于ObvservableCollection,您需要了解两件事。

  1. 如果您直接从其他集合创建它,则不会触发该事件。
  2. 您的args.NewItems.Cast()将始终只在集合中生成一个项目,因为ObservableCollection没有AddRange()方法。
  3. 我看到你来自Winforms。首先检查有关MVVM的更多信息。它会很快得到回报。你需要记住,如果你在控件背后的代码中做任何事情,停止这样做,导致你做错了。 您将在XAML中实例化UserControl。

    <Listbox ItemsSource={Binding Cars}>
        <Listbox.ItemsTemplate>
            <DataTemplate>
                <StackPanel>
                    <my:SmallViews />
                    <my:CompleteViews />
                </StackPanel>
            </DataTemplate>
        </Listbox.ItemsTemplate>
    </Listbox>
    

    你应该真的避免处理

    背后的代码中的任何UI元素