2012-07-19 58 views
5

我有概念的以下证明:这是一个WPF Datagrid的错误?

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á,复选框再次被检查!

我是否错过了一些东西,或者我应该向微软填充一个bug?

编辑:感谢您的回复,但它与INotify或复选框无关,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 
} 
} 
+1

如果您从'INotifyPropertyChanged'继承'Data'并使用属性更改通知,您的结果是否会更改? – Rachel 2012-07-19 18:50:57

+0

尝试关闭回收。该集合是否被调用?如果不是UpdateSourceTrigger =“PropertyChanged”。像雷切尔那样说道。 – Paparazzi 2012-07-19 19:10:22

+0

我会尝试Rachel建议的。 – ecMode 2012-07-19 19:24:31

回答

1

最后,我已经进入了微软的一个缺陷,因为这不是工作的地方或不VirtualRows是预期的方式用过的。

错误报告here

6

这个问题是不相关的循环利用。事实上,禁用回收隐藏了真正的问题:您的对象属性从不更新。尝试在EnabledText设置器中设置断点,您会看到在更改文本或选中/取消选中该框时不会发生任何事情。当您向后滚动时,该属性会从对象中重新读取,并且由于它未更改,所以该复选框会正确更新以匹配Enabled属性。

A DataGrid意味着默认情况下所有行都处于显示模式,用户在需要时切换到当前选定行的编辑模式。在用户验证整个行之前,这些值不会被提交。

在幕后,为整行创建了一个隐含的BindingGroup,将所有绑定有效地设置为UpdateSourceTrigger.Explicit。这个绑定组在用户完成编辑行时被提交。在你的情况下,由于没有BeginEdit,所以不会有任何CommitEdit,并且这些值不会被更新。

您有几种解决方案,在这里:

  • 使用另一个控制不具有这种“切换到编辑模式”的行为,如ListView
  • 在每个绑定上强制将UpdateSourceTrigger设置为PropertyChangedLostFocus
  • 更改用户使用网格的方式以符合DataGrid行为。