我有以下概念证明:
XAML窗口:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" />
<DataGridTemplateColumn >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Mode=TwoWay, Path=Enabled}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Window>
代码背后:
using System.Collections.ObjectModel;
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public ObservableCollection<Data> Items { get; private set; }
public MainWindow()
{
InitializeComponent();
this.Items = new ObservableCollection<Data>();
this.DataContext = this;
for (int index = 0; index < 30; index++)
{
this.Items.Add(new Data() {Enabled = true });
}
}
}
public class Data
{
public bool Enabled { get; set; }
}
}
执行应用程序,取消选中顶部的一些框,向下滚动,再次更改一些框并向上滚动。 Voilá,再次检查复选框!
我是否遗漏了某些内容或是否应该向Microsoft填写错误?
编辑:感谢您的回复,但它与INotify或Checkbox无关,使用TextBox和INotify也会发生同样的情况。你不需要在滚动后点击复选框,只需取消选中,向下滚动,向上滚动,然后再次检查它们。检查此代码:
<DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTemplateColumn >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Mode=TwoWay, Path=Enabled}" />
<TextBox Text="{Binding Text}" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Window>
背后的代码:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public ObservableCollection<Data> Items { get; private set; }
public MainWindow()
{
InitializeComponent();
this.Items = new ObservableCollection<Data>();
this.DataContext = this;
for (int index = 0; index < 30; index++)
{
this.Items.Add(new Data() { Enabled = true, Text = index.ToString() });
}
}
}
public class Data : INotifyPropertyChanged
{
private bool _enabled;
public bool Enabled
{
get { return _enabled; }
set
{
if (value != _enabled)
{
_enabled = value;
this.OnPropertyChanged("Enabled");
}
}
}
private string _text;
public string Text
{
get { return _text; }
set
{
if (value != _text)
{
_text = value;
this.OnPropertyChanged("Text");
}
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string name)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
#endregion
}
}
答案 0 :(得分:6)
此问题与回收无关。事实上,禁用回收隐藏了真正的问题:您的Data
对象属性永远不会更新。尝试在Enabled
或Text
设置器中设置断点,您将看到更改文本或选中/取消选中该框时不会发生任何事情。当您向前和向后滚动时,将从对象重新读取该属性,并且由于它未更改,因此复选框已正确更新以匹配Enabled
属性。
默认情况下,DataGrid
表示所有行都处于显示模式,用户需要时切换到当前所选行的编辑模式。在用户验证整行之前,不会提交这些值。
在幕后,为整行创建了隐式BindingGroup
,有效地将所有绑定设置为UpdateSourceTrigger.Explicit
。用户完成编辑行后,将提交此绑定组。在您的情况下,由于没有BeginEdit
,因此不会有任何CommitEdit
,并且不会更新这些值。
这里有几个解决方案:
ListView
。UpdateSourceTrigger
到PropertyChanged
或LostFocus
。DataGrid
行为的方式。答案 1 :(得分:1)
最后,我在Microsoft输入了一个缺陷,因为无论在何处使用VirtualRows,这都不是预期的工作方式。
错误报告here