5

私は次の概念実証を持っています:

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á、チェックボックスが再びチェックされます!

何かが足りないのですか、それともマイクロソフトにバグを埋める必要がありますか?

編集:ご回答ありがとうございますが、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
}
}
4

2 に答える 2

6

この問題はリサイクルとは関係ありません。実際、リサイクルを無効にすると、本当の問題が隠されますData。オブジェクトのプロパティが更新されることはありません。Enabledまたはセッターにブレークポイントを設定してみてくださいText。テキストを変更したり、チェックボックスをオン/オフにしても何も起こらないことがわかります。スクロールして戻ると、プロパティがオブジェクトから再読み込みされます。プロパティは変更されていないため、チェックボックスはEnabledプロパティに一致するように正しく更新されます。

ADataGridは、デフォルトですべての行を表示モードにすることを意味し、ユーザーは必要に応じて現在選択されている行の編集モードに切り替えます。ユーザーが行全体を検証するまで、値はコミットされません。

舞台裏では、BindingGroup行全体に対して暗黙が作成され、すべてのバインディングが効果的にに設定されUpdateSourceTrigger.Explicitます。このバインディンググループは、ユーザーが行の編集を完了するとコミットされます。あなたの場合、がBeginEditないので、何も存在せずCommitEdit、値が更新されることはありません。

ここにはいくつかの解決策があります:

  • この「編集モードへの切り替え」動作を持たない別のコントロール(など)を使用しListViewます。
  • すべてのバインディングに、またはすべてのバインディングUpdateSourceTriggerを強制します。PropertyChangedLostFocus
  • ユーザーがグリッドを使用して動作に準拠する方法を変更しますDataGrid
于 2012-07-20T12:52:10.177 に答える
1

Finally I've entered a defect at Microsoft because this is not the expected way of working wherever or not VirtualRows are used.

Bug report here

于 2012-07-20T12:15:58.133 に答える