Sono nuovo di WPF e MVVM. Sto lavorando con un team sull’applicazione LoB. Ci piacerebbe avere un controllo Menu
dinamico, che crea il menu in base al profilo utente connesso. Negli scenari di sviluppo precedenti (ovvero ASP.NET), utilizziamo per scorrere i dati che descrivono la raccolta e generare MenuItem
modo dinamico. In MVVM come farei questo? Posso separare la vista XAML da ViewModel che descrive gli elementi del menu?
Soluzione:
Con gli input dei commentatori sono riuscito a bind Menu
modo dinamico con i dati di ViewModel. Anche questo articolo è stato di grande aiuto.
XAML:
[...]
Classe di dati del Menu
:
public class Menu : ViewModelBase { public Menu() { IsEnabled = true; Children = new List(); } #region [ Menu Properties ] private bool _isEnabled; private string _menuText; private ICommand _command; private IList _children; public string MenuText { get { return _menuText; } set { _menuText = value; base.OnPropertyChanged("MenuText"); } } public bool IsEnabled { get { return _isEnabled; } set { _isEnabled = value; base.OnPropertyChanged("IsEnabled"); } } public ICommand Command { get { return _command; } set { _command = value; base.OnPropertyChanged("Command"); } } public IList Children { get { return _children; } set { _children = value; } } #endregion }
Prova qualcosa del genere:
public class MenuItemViewModel { public MenuItemViewModel() { this.MenuItems = new List(); } public string Text { get; set; } public IList MenuItems { get; private set; } }
Supponiamo che il tuo DataContext abbia una proprietà chiamata MenuItems che è un elenco di MenuItemViewModel. Qualcosa del genere dovrebbe funzionare, quindi:
Questo dovrebbe portarti dove stai andando
Nota che nel mio esempio, la mia voce di menu ha una proprietà di tipo ICommand chiamata Command.
Questa soluzione non richiede alcun codice nel codice e ciò rende la soluzione più semplice.
E MenuItem è rappresentato come:
public class MenuItemViewModel : BaseViewModel { /// /// Initializes a new instance of the class. /// /// The parent view model. public MenuItemViewModel(MenuItemViewModel parentViewModel) { ParentViewModel = parentViewModel; _childMenuItems = new ObservableCollection(); } private ObservableCollection _childMenuItems; /// /// Gets the child menu items. /// /// The child menu items. public ObservableCollection ChildMenuItems { get { return _childMenuItems; } } private string _header; /// /// Gets or sets the header. /// /// The header. public string Header { get { return _header; } set { _header = value; NotifyOnPropertyChanged("Header"); } } /// /// Gets or sets the parent view model. /// /// The parent view model. public MenuItemViewModel ParentViewModel { get; set; } public virtual void LoadChildMenuItems() { } }
I MenuItem concreti possono essere istanziati direttamente oppure è ansible creare sottotipi personalizzati attraverso l’ereditarietà.
So che questo è un vecchio post, ma ho bisogno di questo oltre a come bind i comandi.
Per quanto riguarda la domanda di Guge su come associare i comandi: VMMenuItems è una proprietà nel mio tipo di class del modello di visualizzazione
ObservableCollection
e Menu è la class sopra definita. La proprietà Command di MenuItem è associata alla proprietà Command della class Menu. A mio modo di vedere la class del modello
Menu.Command = _fou
dove
private ICommand _fou;
Lo xaml
Se ti stai chiedendo come fare separatori è davvero abbastanza facile.
Il codice seguente è parte del mio ViewModel. Poiché XAML utilizza la reflection, tutto ciò che devo fare è restituire “object” che può essere un MenuItemViewModel
, un Separator
o (se per qualche motivo ho bisogno di farlo) un MenuItem
effettivo.
Sto usando yield
per generare dynamicmente gli articoli perché sembra leggere meglio per me. Anche se sto usando yield
– se gli elementi cambiano, ho ancora bisogno di generare un evento PropertyChanged
per "ContextMenu"
come al solito, ma non genererò inutilmente l’elenco finché non sarà necessario.
public IEnumerable