2009-06-18 13 views
0

私はWPFとMVVMの両方を初めて使用しています。私は動的にMVVMの部分でメニューを作成するための良い方法を探していましたが、私は自分の好みには何も見つかりませんでした。それは動作しますが、何らかの理由でメニューの前景(テキスト)の色が時々(たまには)正しくないことがあります。WPF、MVVM、およびメニュー前景色

下記の画像のリンクを追加しました。

http://img220.imageshack.us/img220/1912/badmenu.jpg (デッドリンク)

私の最も低いサブメニューは、白フォアグラウンドで正しく表示されるが、その親メニューは黒になって、読みすることはほとんど不可能であるforground。私がハードにメニューをコーディングした場合、親の地下色は白です。親にマウスを移動すると、テキストは白に戻り、サブメニューは黒になります。

さらに、親から離れてマウスを移動すると、すべてのブール値のプロパティIsHighlighted, IsSubmenuOpen, etc...が偽になります。これは私が彼らが真実に留まるべきだと思うので驚くべきことです。最終的に私はスタイルトリガーでこれを解決できませんでした。

ここは私の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がWindow.Resources

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

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

実際にすべてのメニューを保持し、ChildMenuItemsコレクションをサブメニューを公開する一般的なクラスから両方ParentMenuChildMenu継承のための私の終了タグをマスキングしています。 ChildMenuItemsChildMenuのオブジェクトのリストです。私のViewModelsParentMenuのオブジェクトを公開しています。

おそらく私がここでしたいものを達成するためのより良い方法があります。次に例を示します。

img132.imageshack.us/img132/4160/bettermenu.jpg (デッドリンク)

私が間違ってやって上の任意の提案および/または表示の問題を修正する方法?

+0

ビューモデルを表示できますか? –

答えて

1

問題は、本質的のMenuItemのヘッダーとしてネストされたのMenuItemを持っているので、あなたのVMは自動的に、のMenuItemに包まれますということです。

DataTypeとしてMenuItemを使用して、VMにDataBinds(Name to Header、DelegateCommands to Commandなど)というスタイルを定義し、ItemContainerStyleでポイントします。

これを行う方法の例は以下のとおりです。 ItemContainerStyleの方がHierarchicalDataTemplateを削除したことに注意してください。私はまた、あなたのMainViewModel用のDataTemplateを定義する自由を取っていました。データバインディングの仕方があまり明確ではなかったからです。

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

簡略化のためにコマンドバインディングの一部を削除しましたが、必要に応じて追加することもできます。

+0

少し微調整が必​​要でしたが、これはうまくいきました。ありがとうございました。 MenuNameプロパティではなく、NameにHeaderバインディングを設定していました。 もう1つは、MainViewModel用のDataTemplateが自分のコードで何もしていないようだということでした。私はいくつかの異なる方法を疲れましたが、私はDockに何かを表示するために "

0

リクエストに応じて、ここに私のViewModelsがあります。

ViewModelBaseは、スタジオによって作成された標準のものです。 MainVieModelは、私が実験に使っていたテストメニューを作成するのに十分なだけ持っています。

基本的に私は、幅広いクライアントに販売する一連のアプリで使用できる親子メニューのクラスを作成するために取り組んでいます。私は、各顧客がニーズに基づいてメニューのカスタマイズ可能なコレクションとライセンスを購入したmoudleを持つことができるようにしたいと考えています。

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: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;  } 
} 
関連する問題