2012-07-19 73 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行爲。