Question

Je suis nouveau dans WPF et MVVM. J'ai cherché un bon moyen de créer dynamiquement des menus dans le partenaire MVVM et je ne trouve rien à mon goût. J'ai donc lancé ma propre solution. Cela fonctionne, mais pour une raison quelconque, la couleur de premier plan (texte) des menus est parfois (juste parfois) incorrecte.

J'ai ajouté un lien pour l'image ci-dessous.

http://img220.imageshack.us/img220/1912/ badmenu.jpg (lien mort)

Mon sous-menu le plus bas s'affiche correctement avec un avant-plan blanc, mais ses menus parents pour l'arrière-plan sont passés au noir et sont presque impossibles à lire. Si j'avais codé les menus en dur, la couleur de fond du parent serait blanche. Si je déplace la souris sur le parent, le texte redevient blanc et le sous-menu devient noir.

De plus, une fois que je déplace la souris du parent, toutes ses propriétés booléennes IsHighlighted, IsSubmenuOpen, etc ... deviennent fausses, ce qui me surprend car je pense qu'elles devraient rester vraies. . Le résultat final est que je n'ai pas été en mesure de résoudre ce problème avec un déclencheur de style.

Voici mon 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 masque ma balise de fin pour Window.Resources

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

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

Les codes ParentMenu et ChildMenu héritent d'une classe commune qui contient tous les menus et expose les sous-menus via la collection ChildMenuItems . ChildMenuItems est une liste d'objets ChildMenu . Mes ViewModels exposent une liste d'objets ParentMenu .

Il existe probablement de meilleurs moyens d’accomplir ce que je veux ici. Voici un exemple:

img132.imageshack.us/img132/4160/bettermenu.jpg (lien mort)

Des suggestions sur ce que je fais mal et / ou comment résoudre le problème d'affichage?

Était-ce utile?

La solution

Le problème est que vos ordinateurs virtuels sont automatiquement encapsulés dans MenuItems. Par conséquent, MenuItems est imbriqué dans l'en-tête de MenuItems.

Vous pouvez contourner ce problème en définissant un style (et en le pointant via ItemContainerStyle) que DataBinds sur vos machines virtuelles (nom vers en-tête, DelegateCommands pour commande, etc.) en utilisant MenuItem comme type de données.

Vous trouverez ci-dessous un exemple de solution. Notez que j'ai abandonné le HierarchicalDataTemplate en faveur d'un ItemContainerStyle. J’ai aussi pris la liberté de définir un DataTemplate pour votre MainViewModel car il n’était pas très clair comment cela était lié aux données.

<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>

J'ai également coupé une partie de la liaison de commande par souci de simplicité, mais vous pouvez la rajouter si nécessaire.

Autres conseils

Comme demandé, voici mes modèles View.

ViewModelBase est le standard créé par studio. MainVieModel en a juste assez pour créer les menus de test que j'utilisais pour expérimenter.

Je travaille essentiellement à la création de classes de menu parent / enfant que je peux utiliser avec une série d'applications que nous vendons à un large éventail de clients. J'espère pouvoir faire en sorte que chaque client puisse disposer d'une collection de menus personnalisable en fonction de ses besoins et pour lequel il a acheté des licences.

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));
        }
    }
}   

Classe publique MainViewModel: 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;     }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top