Domanda

Sono nuovo di WPF e MVVM. Ho cercato un buon modo per creare dinamicamente menu nel parttern MVVM e non trovo nulla di mio gradimento, quindi ho lanciato la mia soluzione. Funziona, ma per qualche ragione il colore in primo piano (testo) dei menu a volte (solo a volte) non è corretto.

Ho aggiunto un link per l'immagine qui sotto.

http://img220.imageshack.us/img220/1912/ badmenu.jpg (Dead Link)

Il mio sottomenu più basso viene visualizzato correttamente con un primo piano bianco, ma i suoi menu principali in primo piano diventano neri ed è quasi impossibile da leggere. Se avessi hard codificato i menu, il colore di primo piano del genitore sarebbe bianco. Se sposto il mouse sul genitore, il testo tornerà al bianco e il sottomenu diventerà nero.

Inoltre, una volta spostato il mouse dal genitore, tutte le sue proprietà booleane IsHighlighted, IsSubmenuOpen, ecc ... diventano false, il che mi sorprende perché penso che dovrebbero rimanere vere . Il risultato finale è che non sono stato in grado di risolverlo con un trigger di stile.

Ecco il mio XAML.

<Window.Resources>
  <DataTemplate DataType="{x:Type src:ParentMenu}" >
    <Menu >
      <MenuItem Header="{Binding MenuName}" ItemsSource="{Binding ChildMenuItems}" />
    </Menu>
  </DataTemplate>

  <HierarchicalDataTemplate DataType="{x:Type src:ChildMenu}" 
                          ItemsSource="{Binding ChildMenuItems}" >
    <MenuItem Header="{Binding MenuName}" Command="{Binding Path=Command}" />
  </HierarchicalDataTemplate>

'StackOverflow sta mascherando il mio tag end per Window.Resources

<DockPanel>
   <Menu DockPanel.Dock="Top" ItemsSource="{Binding Menus}" />

  <Grid>
       <!-- Add additional content here -->
  </Grid>
</DockPanel>

Entrambi ParentMenu e ChildMenu ereditano da una classe comune che detiene effettivamente tutti i menu ed espone i sottomenu attraverso la raccolta ChildMenuItems . ChildMenuItems è un elenco di oggetti ChildMenu . I miei ViewModels espongono un elenco di oggetti ParentMenu .

Probabilmente ci sono modi migliori per realizzare ciò che voglio qui. Ecco un esempio:

img132.imageshack.us/img132/4160/bettermenu.jpg (Dead Link)

Qualche suggerimento su cosa sto facendo di sbagliato e / o su come risolvere il problema di visualizzazione?

È stato utile?

Soluzione

Il problema è che le macchine virtuali vengono automaticamente racchiuse in MenuItems, quindi essenzialmente MenuItems è nidificato come intestazione di MenuItems.

Puoi aggirare il problema definendo uno stile (e puntandolo tramite ItemContainerStyle) che DataBind lega alle tue VM (Name to Header, DelegateCommands to Command, ecc.) usando MenuItem come DataType.

Un esempio di come puoi farlo è di seguito. Nota che ho lasciato cadere HierarchicalDataTemplate a favore di un ItemContainerStyle. Ho anche preso la libertà di definire un DataTemplate per il tuo MainViewModel in quanto non era molto chiaro il modo in cui i dati erano associati.

<Window.Resources>
    <DataTemplate DataType="{x:Type src:MainViewModel}">
        <ItemsControl ItemsSource="{Binding Menus}"></ItemsControl>
    </DataTemplate>
    <DataTemplate DataType="{x:Type src:ParentMenu}" >
        <Menu>
            <MenuItem Header="{Binding Name}" 
        ItemsSource="{Binding ChildMenuItems}" ItemContainerStyle="{DynamicResource ChildMenuItemStyle}" />
        </Menu>
    </DataTemplate>
    <Style x:Key="ChildMenuItemStyle" TargetType="MenuItem">
        <Setter Property="Header" Value="{Binding Name}"></Setter>
        <Setter Property="ItemsSource" Value="{Binding ChildMenuItems}"></Setter>
    </Style>
</Window.Resources>

Ho anche tagliato parte del binding del comando per semplicità, ma è possibile aggiungerlo nuovamente se necessario.

Altri suggerimenti

Come richiesto, ecco i miei ViewModels.

ViewModelBase è quello standard creato da studio. MainVieModel ha abbastanza per creare i menu di test che stavo usando per sperimentare.

Fondamentalmente sto lavorando alla creazione di un menu Genitore / Figlio che posso usare con una serie di app che vendiamo a una vasta collezione di clienti. Spero di riuscire a far sì che ogni cliente possa avere una raccolta personalizzabile di menu in base alle sue esigenze e per quali motivi ha acquistato le licenze.

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

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

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

MainViewModel di classe pubblica: ViewModelBase

{

    public MainViewModel()  {   MakeMenus();    }

    private void MakeMenus()
    {
        // Makes some dummy menus to test with.
        Menus = new ObservableCollection<MyMenuItem>();
        ParentMenu parent;
        ChildMenu child;

        parent = new ParentMenu("First Level");
        Menus.Add(parent);
        child = new ChildMenu(parent, "second level");
        parent.ChildMenuItems.Add(child);
        ChildMenu child2 = new ChildMenu(child, "third level");
        child2.MenuCommand = new DelegateCommand(CommandTest,
                                                   CommandCanExecute_First);
        child.ChildMenuItems.Add(child2);

        child = new ChildMenu(parent, "second level 2");
        parent.ChildMenuItems.Add(child);
        child2 = new ChildMenu(child, "third level 2");
        child2.MenuCommand = new DelegateCommand(CommandTest, 
                                       CommandCanExecute_Second);
        child.ChildMenuItems.Add(child2);

        parent = new ParentMenu("Another First");
        parent.ChildMenuItems.Add(new ChildMenu(parent, "Another Second"));
        Menus.Add(parent);
        OnPropertyChanged("Menus");
    }

    private bool ExecuteToggle { get; set; }
    private void CommandTest()  {   ExecuteToggle = !ExecuteToggle; } 
    public ObservableCollection<MyMenuItem> Menus  {  get; private set;}
    public bool CommandCanExecute_First()   {   return ExecuteToggle;   }
    public bool CommandCanExecute_Second() { return !ExecuteToggle;     }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top