ネタ元:http://d.hatena.ne.jp/okazuki/20100308/1268061755
なんとなく条件がわかってきた。
- DataGridにバインドするクラスがプロパティで値のバリデーションをしていて例外を投げることがある。
- DataGridのセルのバインドにValidatesOnException=Trueが指定してある
- DataGridの行エラーを表示するアイコン?が表示されるタイミングでDataGridの高さが小さい
要は
using System.ComponentModel; using System.ComponentModel.DataAnnotations; namespace DataGridBug { public partial class PersonViewModel : INotifyPropertyChanged, IEditableObject { #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string name) { var h = PropertyChanged; if (h == null) return; h(this, new PropertyChangedEventArgs(name)); } #endregion #region Name Property private string _Name; private string _NameOriginal; [Required(ErrorMessage="Error")] public string Name { get { return _Name; } set { Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "Name" }); _Name = value; OnPropertyChanged("Name"); } } #endregion #region Age Property private int _Age; private int _AgeOriginal; [Range(0, 120, ErrorMessage="please input 0-120")] public int Age { get { return _Age; } set { Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "Age" }); _Age = value; OnPropertyChanged("Age"); } } #endregion #region Memo Property private string _Memo; private string _MemoOriginal; [Required(ErrorMessage="Memo is required")] public string Memo { get { return _Memo; } set { Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "Memo" }); _Memo = value; OnPropertyChanged("Memo"); } } #endregion #region IEditableObject // IEditableObject private bool _isEditing; public void BeginEdit() { if (_isEditing) return; _isEditing = true; _NameOriginal = _Name; _AgeOriginal = _Age; _MemoOriginal = _Memo; } public void CancelEdit() { if (!_isEditing) return; _isEditing = false; _Name = _NameOriginal; _Age = _AgeOriginal; _Memo = _MemoOriginal; } public void EndEdit() { if (!_isEditing) return; _isEditing = false; _NameOriginal = default(string); _AgeOriginal = default(int); _MemoOriginal = default(string); } #endregion } }
↑のようなクラスを
こんな風にバインドして
<Window x:Class="DataGridBug.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" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:my="clr-namespace:DataGridBug" Loaded="Window_Loaded"> <Window.Resources> <CollectionViewSource x:Key="personViewSource" d:DesignSource="{d:DesignInstance my:PersonViewModel, CreateList=True}" /> </Window.Resources> <Grid DataContext="{StaticResource personViewSource}"> <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding}" Margin="12" Name="personDataGrid"> <DataGrid.Columns> <DataGridTextColumn Header="Name" Binding="{Binding Path=Name, ValidatesOnExceptions=True}" /> </DataGrid.Columns> </DataGrid> </Grid> </Window>
適当にデータを流し込む
using System.Linq; using System.Windows; namespace DataGridBug { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { System.Windows.Data.CollectionViewSource personViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("personViewSource"))); personViewSource.Source = Enumerable.Range(1, 1000).Select(i => new PersonViewModel { Name = "test person " + i, Memo = "memomemo" + i }).ToList(); } } }
実行して画面が表示されたら、ウィンドウを小さくしてDataGridに4行くらいしかデータが表示されない状態にする。
どこかのName列の値を編集して空文字にして、ValidationErrorを発生させて、DataGridのRowHeaderに赤いマークを出させる。
たてにスクロールしてみると、DataGridの表示が崩れてる。
これで再現するかな・・・?