0

我目前有一个简单的应用程序,它由两个同步的 ListBox 组成,这些 ListBox 绑定到 ObservableCollections,它们包装了两个不同的实体框架类。

当 listBox1 中的 Part 项目被选中时,它会将SelectedItem的导航键信息传递给 listBox2,listBox2 会显示 Vendors 实体的相应子集。

目前,我的 ViewModel (MainViewModel.cs) 看起来像:

public MainViewModel()
{
    _context = new DBEntities();
    _partsCollection = new ObservableCollection<Part>(_context.Parts);
    _vendorsCollection = new ObservableCollection<Vendor>(_context.Vendors);
}

public ObservableCollection<Part> PartsCollection
{
     get { return _partsCollection; }
     set
     {
          OnPropertyChanged("PartsCollection");
          _partsCollection = value;
     }
}


public Observable<Part> SelectedPart
{
     get { return _selectedPart; }
     set
     {
          OnPropertyChanged("SelectedPart");
          _selectedPart = value;
     }
}

public ObservableCollection<Vendor> VendorsCollection
{
     get { return _vendorsCollection; }
     set
     {
          OnPropertyChanged("VendorsCollection");
          _vendorsCollection = value;
     }
}

我的视图(MainView)看起来像:

    <UserControl.Resources>
    <local:MainViewModel x:Key="MainViewModelDataSource" />
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource MainViewModelDataSource}}">
           <ListBox ItemsSource="{Binding PartsCollection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  Margin="43,87,377,57" Name="listBox1"
             SelectedItem="{Binding SelectedPart, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
             IsSynchronizedWithCurrentItem="True" >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock FontSize="13" Foreground="Black" Padding="3" Text="{Binding shapeName}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <ListBox IsSynchronizedWithCurrentItem="True" 
             ItemsSource="{Binding ElementName=listbox2,  Path=SelectedItem.Vendors, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" Margin="345,87,75,57" 
             >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock FontSize="13" Foreground="Black" Padding="3" Text="{Binding mateStyle}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox> 

这很好用。但是,我想将 listBox2 绑定到我的视图模型的属性以更新VendorsCollection. 我想SelectedPart在我的视图模型上使用“”属性,目前甚至没有使用它。

EF 的全部意义在于将它的所有功能用作 ORM,而不是在我的视图模型中再次构建额外的 ORM 来发送更改通知。据我所见,设置 anICollectionView是一种相当复杂的方法,但我无法弄清楚绑定。

我不确定下一步是什么,以便我可以PropertyChanged发出通知并更新我的 Vendors ObservableCollection,将 listBox2 xaml 绑定到我的视图模型的集合属性。

4

2 回答 2

1

我也在使用 MVVM 和实体框架,但使用代码优先的方法。我厌倦了所有 MVVM 的“纯粹性”,其中 ViewModel 应该引发更改通知事件,所以我在我的所有模型类上实现了 INPC,我从未如此快乐过!在 ViewModel 中复制所有模型属性只是为了通知更改是很疯狂的。

我看到您正在使用 DBEntities,所以我不确定您将如何在模型对象中实现更改通知,但我强烈建议您这样做。我会让你的生活更轻松。

顺便说一句,请务必在将支持字段设置为新值之后引发 OnPropertyChanged 事件,如下所示:

 set
 {
      _selectedPart = value; //first you change the private backing field
      OnPropertyChanged("SelectedPart"); //then you notify that it has changed, so everything gets the new value
 }

关于绑定,您正在使用 ViewModel 的 SelectedPart 属性,此处:

SelectedItem="{Binding SelectedPart, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsSynchronizedWithCurrentItem="True"

您将 listbox1 中的选定项目绑定到 SelectedPart 属性,并且通过将 IsSynchronizedWithCurrentItem 设置为 true,每次您在 UI 中选择某些内容时,ViewModel 中的属性都会更新(反之亦然,如果您将 SelectedPart 设置为代码 UI 将接收更新)。

因此,要绑定到第二个列表框中的 SelectedPart 供应商,只需执行以下操作:

ItemsSource="{绑定 SelectedPart.Vendors, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}"

在这种情况下,您不需要创建 VendorsCollection,因为您可以通过 SelectedPart.Vendors 访问相同的元素(或者您可以将 VendorsCollection 设置为具有好名称的包装器以返回 SelectedPart.Vendor,只需确保检查 SelectedPart 是否为空)。

关于 ICollectionView,知道它只是 ObservableCollection(或类似的)的包装,以便绑定到从 Selector 继承的 FrameworkElements(如 ListBox)(即它们具有 SelectedItem 属性)。

当您绑定到 ObservableCollection 时,WPF 在后台创建一个 ICollectionView,因此您获得了 SelectedItem。您可以创建自己的 ICollectionView,使用 ObservableCollection 提供它,然后绑定到 XAML 中的 ICollectionView,就像使用 ObservableCollection 一样。如果您决定这样做,我建议您使用 ListCollectionView,您可以使用它过滤和创建组(用于树视图)。

最后一句话:记住 ObservableCollection(以及所有 ICollectionViews)只会引发 CollectionChanged 事件(即,当您向集合添加/删除项目时)。如果您更改属于集合的元素的属性,即使它实现 INotifyPropertyChanged,它们也不会引发任何事情。如果您想了解这一点,您必须创建一个自定义集合,这里是一个(众多)示例。

希望这是有用的,问候!

于 2013-01-19T02:27:52.820 回答
0

要开箱即用 PropertyChanged,只需将 ObservableCollection 传递到 BindingList 中。

System.Data.Entity命名空间中的EntityFramework有一个ToBindingList扩展,可以帮助您。

于 2014-01-17T15:39:23.520 回答