2016-11-15 5 views
0

На основании этого sample, я хотел бы добавить, удалить элементы из меню программно, например, таким образом:WPF ObservableCollection и MenuItems

void ChangeItemSubitems() 
    { 
     // TODO: Add event handler implementation here. 
     MenuItems.Add(new MenuItemViewModel { Header = "delta" }); 
     MenuItems[3].MenuItems = new ObservableCollection<MenuItemViewModel>(); 
     MenuItems[3].MenuItems.Add(new MenuItemViewModel { Header = "delta 1" }); 
     MenuItems[3].MenuItems.Add(new MenuItemViewModel { Header = "delta 2" }); 
     MenuItems.Remove(MenuItems[1].MenuItems[0]); 
    } 

Только Добавить деталей на высоком уровне работает отлично , а не подменю, ни Remove. Что это не так? Не могли бы вы дать мне несколько намеков? Благодаря

EDIT: изменения, внесенные в MenuItemViewModel

public class MenuItemViewModel : ViewModelBase 
{ 
    private readonly ICommand _command; 

    public MenuItemViewModel() 
    { 
     _command = new CommandViewModel(Execute); 
    } 

    public MenuItemViewModel(Action action) 
    { 
     _command = new CommandViewModel(action); 
    } 

    private string _header; 

    public string Header 
    { 
     get { return _header; } 
     set 
     { 
      _header = value; 
      RaisePropertyChangedEvent("Header"); 
     } 
    } 

    public ObservableCollection<MenuItemViewModel> MenuItems { get; set; } 

    public ICommand Command 
    { 
     get 
     { 
      return _command; 
     } 
    } 

    private void Execute() 
    { 
     // (NOTE: In a view model, you normally should not use MessageBox.Show()). 
     MessageBox.Show("Clicked at " + Header); 
    } 
} 

public class ViewModelBase : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected void RaisePropertyChangedEvent(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName); 
      PropertyChanged(this, e); 
     } 
    } 
} 
+1

Какой у вас XAML? Используете ли вы «Иерархический файл»? Вы реализуете 'INotifyPropertyChanged' для свойства' MenuItems'? – grek40

+0

@ grek40, XAML совсем то же самое из оригинала ... еще не совсем так. Да, я реализовал INotifyPropertyChanged, но кажется, что он работает нормально (обновляя сам элемент), только если мы изменим исходное дерево. –

ответ

0

Ваша проблема, скорее всего, с

public ObservableCollection<MenuItemViewModel> MenuItems { get; set; } 

Хотя ObservableCollection уведомит UI, когда есть изменения элемента, ваши MenuItemViewModel еще нужно уведомить, когда сама коллекция меняется. Поэтому попробуйте

private ObservableCollection<MenuItemViewModel> _menuItems; 
public ObservableCollection<MenuItemViewModel> MenuItems 
{ 
    get 
    { 
     return _menuItems; 
    } 
    set 
    { 
     _menuItems = value; 
     RaisePropertyChangedEvent("MenuItems"); 
    } 
} 

Редактировать. У удаления есть другая проблема:

MenuItems.Remove(MenuItems[1].MenuItems[0]); 

Это попытка удалить внутреннее подменю из внешней коллекции. Тем не менее, MenuItems[1].MenuItems[0] не является элементом MenuItems, поэтому Remove должен возвращать false в этом случае, и WPF, безусловно, не виноват в том, что он не меняет вид.

Попробуйте следующие вместо:

MenuItems[1].MenuItems.Remove(MenuItems[1].MenuItems[0]); 

Он должен найти и удалить указанный элемент.

+0

Спасибо @ grek40, извините, я не был чист. Нет проблем с параметрами _Add_ и даже _Remove_ в исходном дереве, они были обновлены. Не проблема, если я изменю _Header_ оригиналов, меню или подменю. Это не работает, если я пытаюсь добавить новое подменю ... –

+0

@ G.Zana Итак, вы реализовали мое предложение, и оно не работает? потому что такие вещи, как 'MenuItems [3] .MenuItems = new ObservableCollection ();' должны вести себя иначе, когда изменение свойства будет правильно уведомлено. – grek40

+0

... он не работает, если я пытаюсь удалить существующие подменю. –

Смежные вопросы