2012-02-02 125 views
5

我有一個DataGrid用戶可以通過在最後一行輸入數據添加項目。我也有一個刪除當前選擇的項目的按鈕。但是,如果選擇最後一個(用於添加新項目的空白)行,最後選擇的項目將保留在SelectedItem中。因此,如果我打開窗口,選擇最後一行,然後按下刪除按鈕,它將刪除第一行,因爲它是默認選擇的,選擇最後一行不會改變SelectedItem。處理這個問題的好辦法?WPF DataGrid SelectedItem

澄清: 的SelectedItem =「{結合X}」

X在視圖模型被選擇的最後一行時不改變(設置器不是在所有調用的)。我不確定SelectedItem屬性本身是否更改,但我會認爲它不會。

當我選擇最後一行(紅色邊框)時也有一個例外,但是當我再次單擊它以開始輸入數據時,紅色邊框消失。不確定這兩者是否有關係。

回答

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().Name是否爲NamedObject

+2

5年後,但不妨將它放在這裏:您可以將它與CollectionView.NewItemPlaceholder進行比較,它與您正在做的事情相同,無需在代碼中刻錄「{NewItemPlaceholder}」字符串。 – 2017-03-24 22:27:03

0

很難說沒有代碼,但我會看看下面的內容。

確保無論何時刪除一個項目並且它也是選定的項目,請將在ViewModel中綁定到屬性的選定項目設置爲null。你需要確保你的SelectedItem綁定到屬性不是單向綁定的。

0

聽起來你忘了設置綁定模式,並且默認設置爲OneWay。這意味着無論您在視圖中所做的任何更改都不會傳播回您的視圖模型。

並始終確保您有正確的數據上下文。

希望有所幫助。

相關問題