WPF:两个DataGrid,相同的ItemsSource,一个是只读的,是否有Bug?

3
我有一个WPF应用程序,其中有两个DataGrid共享相同的ItemsSource。当我将其中一个DataGrid的IsReadOnly属性设置为true时,我失去了向另一个DataGrid添加记录的能力。我仍然可以编辑第二个DataGrid的内容,但是无法添加记录。
这是预期的吗?有没有办法解决这个问题?我可以使用IsEnabled="False"来禁用DataGrid,但这样会失去在其中滚动的能力。
以下是设置:
XAML:
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <DataGrid Name="dgA" Grid.Row="0" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="FirstName" Binding="{Binding Path=FirstName}" />
            <DataGridTextColumn Header="LastName" Binding="{Binding Path=LastName}" />
        </DataGrid.Columns>         
    </DataGrid>
    <DataGrid Name="dgB" Grid.Row="1" AutoGenerateColumns="False" IsReadOnly="True">
        <DataGrid.Columns>
            <DataGridTextColumn Header="FirstName" Binding="{Binding Path=FirstName}" />
            <DataGridTextColumn Header="LastName" Binding="{Binding Path=LastName}" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>

C#:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        List<Person> persons = new List<Person>();
        persons.Add(new Person() { FirstName = "Bob", LastName = "Johnson" });
        persons.Add(new Person() { FirstName = "John", LastName = "Smith" });

        dgA.ItemsSource = persons;
        dgB.ItemsSource = persons;
    }

    class Person
    {
        public Person() { }

        public string FirstName
        {
            get;
            set;
        }

        public string LastName
        {
            get;
            set;
        }
    }
}

你的意思是通过编程方式添加记录(例如在MainWindow构造函数中使用C#)吗? - Mario Vernari
DataGrid通常处于非只读模式时会有一个空行,可用于添加记录。但在此实例中,该空行不再可用。我尚未尝试通过编程方式添加记录。 - Khan
可能将dgB的数据绑定设置为单向绑定? - Roy T.
1个回答

6
我认为的问题是,通过persons的DefaultView,IsReadOnly属性使DataGrid只读,由于这个DefaultView将是两个DataGrid的相同,因此两者都失去了添加新行的能力。
然而,两者并不变成只读(正如你在问题中所说),所以我不确定这是一个bug还是预期的行为。
我也不确定在幕后发生了什么导致了这种行为,但你可以通过调试器验证CollectionView是否相同(因为CollectionView属性是私有的)。以下三个语句结果为true。
dgA.Items.CollectionView == CollectionViewSource.GetDefaultView(persons) // true
dgB.Items.CollectionView == CollectionViewSource.GetDefaultView(persons) // true
dgA.Items.CollectionView == dgB.Items.CollectionView // true

您可以通过将List更改为ObservableCollection,并使用单独的ListViewCollection来使DataGrid's按您喜欢的方式工作。

public MainWindow()
{
    InitializeComponent();

    ObservableCollection<Person> persons = new ObservableCollection<Person>();
    persons.Add(new Person() { FirstName = "Bob", LastName = "Johnson" });
    persons.Add(new Person() { FirstName = "John", LastName = "Smith" });

    dgA.ItemsSource = new ListCollectionView(persons);
    dgB.ItemsSource = new ListCollectionView(persons);
}

+1 是帮助我理解正在发生的事情。但这并不能给我想要的功能。我希望第二个网格包含第一个网格所包含的所有内容,并且在第一个网格发生更改时也进行更改。当我编辑第一个网格中的项目时,它确实会在第二个网格中发生更改。但不幸的是,在第一个网格中添加或删除记录不会影响第二个网格。 - Khan
@Jeff:你把List改成了ObservableCollection吗?我刚试了一下,它可以用于编辑单元格和添加/删除行。 - Fredrik Hedblad
1
顺便提一下,由于使用了相同的集合视图,排序顺序也会受到影响... - Eric Ouellet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接