2017-07-31 85 views
0

绑定到CollectionView源时,所有行显示最初显示的空白值,然后当我更改任何组合框的选择时,所有组合框都设置为相同的值。当我直接绑定到ObservableCollection的源集合时,它可以正常工作。我想使用一个CollectionViewSource,这样我就可以利用它的排序功能等。下面是一些代码,它使用一个绑定到CollectionViewSource的列和一个直接绑定到底层ObservableCollection的方法来解决问题。我使用VS 2015将数据网格组合框列绑定到CollectionViewSource时的奇怪行为

视图模型:

public class GridItem 
{ 
    public string Name { get; set; } 
    public int CompanyID { get; set; } 
    public int CompanyID2 { get; set; } 
} 

public class CompanyItem 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
} 

public class ViewModel 
{ 
    public ViewModel() 
    { 
     GridItems = new ObservableCollection<GridItem>() { 
      new GridItem() { Name = "Jim", CompanyID = 1, CompanyID2 = 1 }, 
      new GridItem() { Name = "Ed", CompanyID = 2, CompanyID2 = 2 }, 
      new GridItem() { Name = "Dave", CompanyID = 3, CompanyID2 = 3 }, 
      new GridItem() { Name = "Bruce", CompanyID = 4, CompanyID2 = 4 }, 
      new GridItem() { Name = "Rob", CompanyID = 5, CompanyID2 = 5 } 
     }; 

     CompanyItems = new ObservableCollection<CompanyItem>() { 
      new CompanyItem() { ID = 1, Name = "Company 1" }, 
      new CompanyItem() { ID = 2, Name = "Company 2" }, 
      new CompanyItem() { ID = 3, Name = "Company 3" }, 
      new CompanyItem() { ID = 4, Name = "Company 4" }, 
      new CompanyItem() { ID = 5, Name = "Company 5" }, 
      new CompanyItem() { ID = 6, Name = "Company 6" }, 
      new CompanyItem() { ID = 7, Name = "Company 7" }, 
     }; 

     CompanyItemsViewSource = new CollectionViewSource(); 
     CompanyItemsViewSource.Source = CompanyItems; 
    } 

    public ObservableCollection<GridItem> GridItems { get; set; } 
    public ObservableCollection<CompanyItem> CompanyItems { get; set; } 
    public CollectionViewSource CompanyItemsViewSource { get; set; } 
} 

的窗口:

<Window x:Class="DataGridTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:DataGridTest" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding GridItems}" > 
      <DataGrid.Columns> 
       <DataGridTextColumn Binding="{Binding Name}" Header="Name"/> 

       <DataGridComboBoxColumn 
        SelectedValueBinding="{Binding CompanyID}" DisplayMemberPath="Name" SelectedValuePath="ID" Header="Company (View Source)"> 
        <DataGridComboBoxColumn.ElementStyle> 
         <Style TargetType="{x:Type ComboBox}"> 
          <Setter Property="ItemsSource" Value="{Binding Path=DataContext.CompanyItemsViewSource.View, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" /> 
         </Style> 
        </DataGridComboBoxColumn.ElementStyle> 
        <DataGridComboBoxColumn.EditingElementStyle> 
         <Style TargetType="{x:Type ComboBox}"> 
          <Setter Property="ItemsSource" Value="{Binding Path=DataContext.CompanyItemsViewSource.View, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" /> 
         </Style> 
        </DataGridComboBoxColumn.EditingElementStyle> 
       </DataGridComboBoxColumn> 

       <DataGridComboBoxColumn 
        SelectedValueBinding="{Binding CompanyID2}" DisplayMemberPath="Name" SelectedValuePath="ID" Header="Company"> 
        <DataGridComboBoxColumn.ElementStyle> 
         <Style TargetType="{x:Type ComboBox}"> 
          <Setter Property="ItemsSource" Value="{Binding Path=DataContext.CompanyItems, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" /> 
         </Style> 
        </DataGridComboBoxColumn.ElementStyle> 
        <DataGridComboBoxColumn.EditingElementStyle> 
         <Style TargetType="{x:Type ComboBox}"> 
          <Setter Property="ItemsSource" Value="{Binding Path=DataContext.CompanyItems, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" /> 
         </Style> 
        </DataGridComboBoxColumn.EditingElementStyle> 
       </DataGridComboBoxColumn> 
      </DataGrid.Columns> 
     </DataGrid> 
    </Grid> 
</Window> 

数据上下文设置应用程序启动时:

public partial class App : Application 
{ 
    protected override void OnStartup(StartupEventArgs e) 
    { 
     base.OnStartup(e); 

     MainWindow window = new MainWindow(); 
     ViewModel viewModel = new ViewModel(); 

     window.DataContext = viewModel; 
     window.Show(); 
    } 
} 
+0

你试过用'Collec tionViewSource'在XAML?例如'',然后在您的'DataGrid'中'。 – XAMlMAX

回答

1

要绑定同一个CollectionViewSource的所有不同行的相同视图。当您更改其中一个行时,您正在操纵底层视图,该视图将在其他行上进行复制。

您需要针对不同的行具有不同的集合视图。要仅使用一个属性来执行此操作,每次调用get访问器时都可以创建一个新视图。

ICollectionView类型的新属性添加到您的视图模型是这样的:

public ICollectionView CompanyItemCollectionView 
{ 
    get 
    {    
     return new CollectionViewSource { Source = CompanyItems }.View; 
    } 
} 

绑定这个属性到您的DataGridComboBoxColumn的元素的ItemsSource:

<DataGridComboBoxColumn 
SelectedValueBinding="{Binding CompanyID}" DisplayMemberPath="Name" SelectedValuePath="ID" Header="Company (ICollectionView)"> 
    <DataGridComboBoxColumn.ElementStyle> 
     <Style TargetType="{x:Type ComboBox}"> 
      <Setter Property="ItemsSource" Value="{Binding Path=DataContext.CompanyItemCollectionView, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" /> 
     </Style> 
    </DataGridComboBoxColumn.ElementStyle> 
    <DataGridComboBoxColumn.EditingElementStyle> 
     <Style TargetType="{x:Type ComboBox}"> 
      <Setter Property="ItemsSource" Value="{Binding Path=DataContext.CompanyItemCollectionView, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" /> 
     </Style> 
    </DataGridComboBoxColumn.EditingElementStyle> 
</DataGridComboBoxColumn> 

您可以设置过滤器和排序订购里面的获取访问者太:

public ICollectionView CompanyItemCollectionView 
{ 
    get 
    { 
     ICollectionView view = new CollectionViewSource { Source = CompanyItems }.View; 
     view.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Descending)); //example     
     return view; 
    } 
} 
+0

非常感谢。为每一行创建视图不是很沉重吗? – Shane

+0

我对性能并不确定。我会说它会好的,这取决于你所拥有的行数。但是:https://blogs.msdn.microsoft.com/audiofool/2007/06/14/the-rules-of-code-optimization/试一试,看看它是否满足您的需求。如果没有,请搜索另一个解决方案。 –