2015-02-23 20 views
5

Bu sorunu olabildiğince küçültdüm. Temel olarak bir combobox'ın "boş" değerini geçersiz kılıyorum. Böylece seçilen öğe silinirse, "(null)" olarak geri döner. Ne yazık ki, bunun davranışının yanlış olduğunu, Silmeyi sildim, ObservableCollection öğesi kaldırıldı, böylece özellik bağlama güncelleştirilir ve "(null)" öğeyi beklendiği gibi döndürür. Ancak açılan kutu görünümü boş gösteriliyor. Yine de onun bağlı olduğu değer doğrudur ... bu problem aşağıdaki kodla çoğaltılabilir.WPF DisplayMemberPath SelectedItem kaldırıldığında güncellenmiyor

Bu sorunu yeniden üretmek için bir öğe seçip kaldır düğmesine basın. Bu noktada dikkat edilmesi gereken nokta (seçilen öğeyi kaldırdığınızda). Yani onun kırılması için iyi bir yer.

   if (m_Selected == null) 
      { 
       return Items[0]; //items 0 is ItemNull 
      } 

Ayrıca ben DisplayMemberPath bir özellik güncelleştirme zorlamak bu sorunu çözmeyi attmpted dikkat edin. Bu işe yaramadı.

MainWindow.xaml

<Window x:Class="WPFCodeDump.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"> 
    <StackPanel> 
     <ComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding Selected, Mode=TwoWay}" DisplayMemberPath="Name"></ComboBox> 
     <Button Click="ButtonBase_OnClick">Remove Selected</Button> 
    </StackPanel> 
</Window> 

MainWindowViewModel.cs

using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.Runtime.CompilerServices; 
using System.Windows.Input; 

namespace WPFCodeDump 
{ 
    public abstract class ViewModelBase : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "") 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 

    //Item class 
    public class Item : ViewModelBase 
    { 
     public Item(string name) 
     { 
      m_Name = name; 
     } 

     public string Name 
     { 
      get { return m_Name; } 
     } 
     private string m_Name; 

     public void ForcePropertyUpdate() 
     { 
      OnPropertyChanged("Name"); 
     } 
    } 

    //Item class 
    public class ItemNull : Item 
    { 
     public ItemNull() 
      : base("(null)") 
     { 
     } 
    } 

    class MainWindowViewModel : ViewModelBase 
    { 
     public MainWindowViewModel() 
     { 
      m_Items.Add(new ItemNull()); 
      for (int i = 0; i < 10; i++) 
      { 
       m_Items.Add(new Item("TestItem" + i)); 
      } 
      Selected = null; 
     } 

     //Remove selected command 
     public void RemoveSelected() 
     { 
      Items.Remove(Selected); 
     } 

     //The item list 
     private ObservableCollection<Item> m_Items = new ObservableCollection<Item>(); 
     public ObservableCollection<Item> Items 
     { 
      get { return m_Items; } 
     } 

     //Selected item 
     private Item m_Selected; 
     public Item Selected 
     { 
      get 
      { 
       if (m_Selected == null) 
       { 
        return Items[0]; //items 0 is ItemNull 
       } 
       return m_Selected; 
      } 
      set 
      { 
       m_Selected = value; 
       OnPropertyChanged(); 
       if(m_Selected!=null) m_Selected.ForcePropertyUpdate(); 
      } 
     } 
    } 
} 

MainWindow.xaml.cs

using System.Windows; 

namespace WPFCodeDump 
{ 


    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      DataContext = new MainWindowViewModel(); 
     } 

     private void ButtonBase_OnClick(object sender, RoutedEventArgs e) 
     { 
      ((MainWindowViewModel) DataContext).RemoveSelected(); 
     } 
    } 
} 

Sonuç:

Result after pressing remove

+0

* İade Maddeleri [0] * ... dönüşü ne? Ne yapması gerekiyor? Şüphesiz sadece ihtiyacınız var 'Seçilen = Öğeler [0]' (Öğelerin [0] 'ın veriye bağlı koleksiyondan gerçek bir öğe olduğunu varsayarak). – Sheridan

+0

SelectedItem-Binding'da 'UpdateSourceTrigger = PropertyChanged' ayarlamayı denediniz mi? – Tomtom

+0

Öğe, m_Items – Asheh

cevap

3

Orada bulduğunuz güzel bir bağ sorunu. Ama her zamanki gibi, bu bizim hatamız değil, onların değil :)

DisplayMemberPath kullanarak SelectedItem ile sorun (vardır). DisplayMemberPath, SelectedItem değiştirilen hakkında bir f *** vermez.

Birincisi, RemoveSelected yöntemde, null Selected özelliğini ayarlayın (bağlayıcı bir güncelleme zorlamak için):

bu sorunu gidermek için, yapman gereken şey, iki şey

public void RemoveSelected() 
{ 
    Items.Remove(Selected); 
    Selected = null; 
} 

Daha sonra, XAML tanımı, bağlanmış özelliği değiştirmek: Bağlanma

<ComboBox ItemsSource="{Binding Items}" 
      SelectedValue="{Binding Selected, Mode=TwoWay}" 
      DisplayMemberPath="Name"/> 

SelectedValue özelliği u doğru olacak Görüntülenen metni ComboBox'da pdate.

+0

Vay bu işe yarıyor. "Selected = null" etrafında dolaşmanın bir yolu var mı? Koddaki noktada ne yazık ki Selected (benim örneğimde olduğu gibi) hakkında bilmiyorum. Ancak bu konuda ItemsSource OnCollectionChanged olayına abone olabilirdim. – Asheh

+0

Daha açık olduğu için üzgünüz. Seçtiğim öğe koleksiyona bağlı olduğunu bilmiyor. – Asheh

+0

Sanırım her ikisini de bilen bir yerde yapmalısın ...? – Herdo

İlgili konular