2009-06-18 91 views
0

我是WPF和MVVM的新手。我尋找了一種在MVVM parttern中動態創建菜單的好方法,我沒有找到任何符合我喜好的東西,所以我推出了自己的解決方案。它可以工作,但由於某些原因,菜單的前景(文本)顏色有時(有時)不正確。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> 

兩個ParentMenu,並從實際持有的所有菜單和普通類ChildMenu繼承通過ChildMenuItems集合公開的子菜單。 ChildMenuItems是一個ChildMenu對象的列表。我的ViewModels公開了一個ParentMenu對象的列表。

有可能有更好的方法來完成我想在這裏。這裏有一個例子:

img132.imageshack.us/img132/4160/bettermenu.jpg (死鏈接)

什麼我做錯了任何建議和/或如何解決顯示問題?

+0

我們可以看到視圖模型嗎? – 2009-06-18 13:41:46

回答

1

的問題是,你的虛擬機自動獲得裹的MenuItems,所以你基本上是有嵌套作爲的MenuItems的頭的MenuItems。

你可以通過使用MenuItem作爲DataType定義一個DataBinds到你的VMs(Name到Header,DelegateCommands to Command等)的Style(並指向它通過ItemContainerStyle)來解決這個問題。

下面是您可以執行此操作的一個示例。請注意,我已經放棄了HierarchicalDataTemplate以支持ItemContainerStyle。我也爲您的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屬性。 另一個是MainViewModel的DataTemplate似乎沒有在我的代碼中做任何事情。我厭倦了幾種不同的方式,但我需要Dock中的「

2009-06-18 19:45:13

0

按照要求,這裏是我的ViewModels。

ViewModelBase是Studio創建的標準版本。 MainVieModel已經足夠用來創建我正在使用的測試菜單進行試驗。

基本上我正在努力創建一個父/子菜單類,我可以使用一系列應用程序,我們銷售給廣泛的客戶端集合。我希望能讓每個客戶都能根據自己的需求獲得可定製的菜單集合,以及他們購買許可證的模塊。

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