2012-02-02 38 views
5

私はDataGridを持っています。ユーザは最後の行にデータを入力することで項目を追加できます。私はまた、現在選択されている項目を削除するボタンがあります。しかし、新しい項目を追加するための最後の(空の)行が選択されたとき、最後に選択された項目は、SelectedItemに残ります。したがって、ウィンドウを開いて最後の行を選択し、deleteボタンを押すと、デフォルトで選択されている最初の行が削除され、最後の行を選択してもSelectedItemは変更されません。これに対処する良い方法はありますか? WPF DataGrid SelectedItem

は、明確にするために: のSelectedItem =「{バインディングX}」最後の行が選択された場合(セッターが全く起動されていない)は変化しないビューモデルで

X。 SelectedItemプロパティ自体が変更されるかどうかはわかりませんが、そうではないと思います。

最後の行(赤い枠)を選択すると例外がありますが、データを入力するためにもう一度クリックすると赤い枠が消えます。これらの2つが関連しているかどうかは不明です。

答えて

10

次の例を実行すると、動作しない理由がわかります。

XAML:

<Window x:Class="DataGridTest.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"> 
    <DockPanel> 
     <TextBlock DockPanel.Dock="Bottom" Text="{Binding SelectedItem, ElementName=dataGrid}"/> 
     <TextBlock DockPanel.Dock="Bottom" Text="{Binding SelectedItem}"/> 
     <DataGrid x:Name="dataGrid" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" CanUserAddRows="True" CanUserDeleteRows="True" AutoGenerateColumns="False"> 
      <DataGrid.Columns> 
       <DataGridTextColumn Header="First Name" Binding="{Binding FirstName}"/> 
       <DataGridTextColumn Header="Last Name" Binding="{Binding FirstName}"/> 
      </DataGrid.Columns> 
     </DataGrid> 
    </DockPanel> 
</Window> 

コードビハインド:

namespace DataGridTest 
{ 
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.ComponentModel; 
    using System.Windows; 

    public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     private readonly ICollection<Person> items; 
     private Person selectedItem; 

     public MainWindow() 
     { 
      InitializeComponent(); 

      this.items = new ObservableCollection<Person>(); 
      this.items.Add(new Person 
       { 
        FirstName = "Kent", 
        LastName = "Boogaart" 
       }); 
      this.items.Add(new Person 
      { 
       FirstName = "Tempany", 
       LastName = "Boogaart" 
      }); 

      this.DataContext = this; 
     } 

     public ICollection<Person> Items 
     { 
      get { return this.items; } 
     } 

     public Person SelectedItem 
     { 
      get { return this.selectedItem; } 
      set 
      { 
       this.selectedItem = value; 
       this.OnPropertyChanged("SelectedItem"); 
      } 
     } 

     private void OnPropertyChanged(string propertyName) 
     { 
      var handler = this.PropertyChanged; 

      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
    } 

    public class Person 
    { 
     public string FirstName 
     { 
      get; 
      set; 
     } 

     public string LastName 
     { 
      get; 
      set; 
     } 

     public override string ToString() 
     { 
      return FirstName + " " + LastName; 
     } 
    } 
} 

実行しているときに見ることができるように、「新しい」行で選択した項目として設定することがセンチネル値を引き起こし選択DataGrid。ただし、WPFはそのセンチネルアイテムをPersonに変換できないため、SelectedItemバインディングの変換に失敗します。

これを修正するには、検出器を検出したバインダーにコンバーターを置き、nullを返します。ここではそうコンバータだ:

namespace DataGridTest 
{ 
    using System; 
    using System.Windows.Data; 

    public sealed class SentinelConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      return value; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      if (value != null && string.Equals("{NewItemPlaceholder}", value.ToString(), StringComparison.Ordinal)) 
      { 
       return null; 
      } 

      return value; 
     } 
    } 
} 

あなたが見ることができるように、それは内部型ですので、センチネルのToString()値に対してテストする不幸な必要性です。代わりに(またはさらに)GetType().NameNamedObjectであることを確認することもできます。

+2

5年後ですが、ここに入れることもできます:コードに「{NewItemPlaceholder}」文字列を書き込む必要なく、同じことを行うCollectionView.NewItemPlaceholderと比較することができます。 –

0

コードなしで言うのは難しいですが、私は以下を見ていきます。

アイテムが削除され、選択されたアイテムでも常に、ViewModelのプロパティにバインドされた選択項目をnullに設定してください。 SelectedItemへのバインドが一意に束縛されていないことを確認する必要があります。

0

バインディングモードを設定するのを忘れているようですが、デフォルトはOneWayに設定されています。つまり、ビューで行った変更は、ビューモデルに反映されません。

そして、常に正しいデータコンテキストがあることを確認してください。

希望に役立ちます。