Frage

Ich bin neu sowohl WPF und MVVM. Ich habe für eine gute Möglichkeit gesucht, um dynamisch Menüs in der MVVM zu erstellen parttern und ich bin nicht nach meinem Geschmack zu finden, etwas, so rollte ich meine eigene Lösung. Es funktioniert, aber aus irgendeinem Grund der Vordergrund (Text) Farbe der Menüs sind manchmal (nur manchmal) nicht korrekt.

Ich habe einen Link für das Bild unten.

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

Meine tiefste Untermenü richtig angezeigt wird mit einem weißen Vordergrund, aber seine Eltern Menüs Forground zu schwarz geworden und ist fast unmöglich zu lesen. Wenn ich hart, um die Menüs codiert hatte dann würde die forground Farbe der Eltern sein weiß. Wenn ich meine Maus über die Eltern ihren Text bewegen wird weiß wechseln und das Untermenü wird schwarz.

Außerdem, wenn ich weg von der Mutter meiner Maus bewegen, alle seiner boolean Eigenschaften falsch IsHighlighted, IsSubmenuOpen, etc... worden, was für mich überraschend, weil ich denke, dass sie treu bleiben sollten. Das Endergebnis ist, habe ich nicht in der Lage gewesen, dies mit einem Stil-Trigger zu lösen.

Hier ist meine 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 maskiert meinen End-Tag für Window.Resources

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

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

Sowohl ParentMenu und ChildMenu von einer gemeinsamen Klasse erben, die alle Menüs tatsächlich hält und macht die Untermenüs durch die ChildMenuItems Sammlung. ChildMenuItems ist eine Liste von ChildMenu Objekte. Mein ViewModels eine Liste von ParentMenu Objekten aus.

Es gibt wahrscheinlich bessere Wege zu erreichen, was ich hier will. Hier ein Beispiel:

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

Alle Vorschläge, was ich falsch mache und / oder wie das Anzeigeproblem zu beheben?

War es hilfreich?

Lösung

Das Problem ist, dass Ihre VMs automatisch in MenuItems eingewickelt bekommen, so dass Sie im Wesentlichen MenuItems als Header von MenuItems verschachtelt sind.

Sie können dies umgehen, indem Sie einen Style zu definieren (und auf sie zeigen über ItemContainerStyle), dass DataBinds auf Ihren VMs (Name Kopfzeile, DelegateCommands Command, etc.) mit MenuItem als Datentyp.

Ein Beispiel für eine Art und Weise, dies zu tun ist unten. Beachten Sie, dass ich die HierarchicalDataTemplate zugunsten eines ItemContainerStyle fallen gelassen habe. Ich habe auch die Freiheit, eine Datatemplate für Ihren MainViewModel definieren, da es nicht ganz klar war, wie das war Daten gebunden.

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

Ich habe auch einige der Befehls schneiden der Einfachheit halber Bindung aus, aber man kann es sich als notwendig, wieder hinzufügen.

Andere Tipps

Wie gewünscht, hier sind meine Viewmodel.

ViewModelBase ist der Standard eines von Studio erstellt. MainVieModel hat gerade genug bekam darin, den Test Menüs zu erstellen, mit dem ich zu experimentieren wurde mit.

Im Grunde arbeite ich ein Eltern- / Kind-Menü Klassen zur Schaffung ich mit einer Reihe von Apps nutzen, können wir auf eine breite Sammlung von Kunden zu verkaufen. Ich hoffe, es zu machen, wo jeder Kunde eine individuell anpassbare Sammlung von Menüs auf ihre Bedürfnisse auf Basis haben können und welche moudles sie für erworbene Lizenzen haben.

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

public class 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;     }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top