簡體   English   中英

將數據網格組合框列綁定到CollectionViewSource時的奇怪行為

[英]Strange behavior when binding data grid combo box column to CollectionViewSource

當綁定到CollectionView源時,所有行最初顯示為空白值,然后當我更改任何組合框上的選擇時,所有組合框都設置為相同的值。 當我直接綁定到ObservableCollection的源集合時,它可以正常工作。 我想使用CollectionViewSource,以便可以利用其排序功能等。這是一些說明問題的代碼,其中一列綁定到CollectionViewSource,一個直接綁定到基礎ObservableCollection。 我正在使用VS 2015。

視圖模型:

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();
    }
}

您將同一CollectionViewSource的相同視圖綁定到所有不同的行。 更改其中一行時,您正在操縱基礎視圖,該視圖將在其他行上復制。

您需要為不同的行使用不同的集合視圖。 為此,只需使用一個屬性,就可以在每次調用get訪問器時創建一個新視圖。

像這樣將ICollectionView類型的新屬性添加到您的ViewModel中:

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>

您也可以在get訪問器中設置過濾器和排序順序:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM