2012-10-23 18 views
6

मैं एक WPF अनुप्रयोग बना रहा हूं जो एमवीवीएम सिद्धांतों के साथ निकटता से टिकने की कोशिश कर रहा है। मुझे मेनू को सही ढंग से प्रस्तुत करने में समस्या आ रही है। मैंने कुछ दृष्टिकोणों की कोशिश की है और अटक गया है। ऐसा लगता है कि मेरी बाध्यकारी सही है, लेकिन मुझे अपने शैलियों में हेरफेर के बारे में निश्चित नहीं है।HierarchicalDataTemplate का उपयोग करके बाध्यकारी WPF मेनू मेनू आइटम को उचित रूप से प्रस्तुत नहीं कर रहा है

यहां कोड है जिसमें मुझे समस्या है। जैसे मैंने कहा, ऐसा लगता है कि बाध्यकारी अच्छा है, और मैं स्नूप का उपयोग कर हेडर मेनू आइटम के लिए सही मान भी देख सकता हूं, लेकिन मुझे लगता है कि मेनू आइटम के लिए खाली कंटेनर हैं।

<DockPanel> 
     <DockPanel.Resources> 
      <HierarchicalDataTemplate x:Key="TopMenuHDT" ItemsSource="{Binding Children}"> 
       <HierarchicalDataTemplate.ItemContainerStyle> 
        <Style TargetType="{x:Type MenuItem}"> 
         <Setter Property="Command" Value="{Binding Command}" /> 
         <Setter Property="Header" Value="{Binding MenuText}" /> 
         <Setter Property="Icon"> 
          <Setter.Value> 
           <Image Source="{Binding MenuIcon}" Height="16px" Width="16px" /> 
          </Setter.Value> 
         </Setter> 
        </Style> 
       </HierarchicalDataTemplate.ItemContainerStyle> 
      </HierarchicalDataTemplate> 

     </DockPanel.Resources> 
     <Menu DockPanel.Dock="Top" Height="auto" 
       ItemsSource="{Binding TopMenuItems}" 
       ItemTemplate="{StaticResource TopMenuHDT}"/> 

अपने मुख्य ViewModel में:

private ObservableCollection<MenuViewModel> _topMenuItems; 
    public ObservableCollection<MenuViewModel> TopMenuItems 
    { 
     get { return _topMenuItems; } 
     set 
     { 
      if (_topMenuItems == value) 
       return; 

      _topMenuItems = value; base.RaisePropertyChanged("TopMenuItems"); 
     } 
    } 
... 
    public void LoadMainMenu() 
    { 
     IList<ViewModels.MenuViewModel> fileMenuItems = PopulateFileMenuEntries(); 
     IList<ViewModels.MenuViewModel> editMenuItems = PopulateEditMenuEntries(); 

     _topMenuItems.Add(new ViewModels.MenuViewModel() { MenuText = "_File", Children = new ObservableCollection<ViewModels.MenuViewModel>(fileMenuItems) }); 
     _topMenuItems.Add(new ViewModels.MenuViewModel() { MenuText = "_Edit", Children = new ObservableCollection<ViewModels.MenuViewModel>(editMenuItems) }); 

    private IList<ViewModels.MenuViewModel> PopulateFileMenuEntries() 
    { 
     List<ViewModels.MenuViewModel> fileMenuItems = new List<ViewModels.MenuViewModel>(); 

     fileMenuItems.Add(new ViewModels.MenuViewModel() { MenuText = "_Open", MenuIcon = new BitmapImage(new Uri("pack://application:,,,/Resources/OpenDocument16.png")) , Command = _mainWindowViewModel.OpenCommand }); 
     fileMenuItems.Add(new ViewModels.MenuViewModel() { MenuText = "Open _Recent" }); 

     return fileMenuItems; 
    } 

MenuViewModel:

public class MenuViewModel : ObservableObject 
{ 
    internal MenuViewModel() 
    { 
     IsEnabled = true; 
    } 

    private string _menuText; 
    public string MenuText 
    { 
     get { return _menuText; } 
     set 
     { 
      if (_menuText == value) 
       return; 

      _menuText = value; base.RaisePropertyChanged("MenuText"); 
     } 
    } 

    private ICommand _command; 
    public ICommand Command 
    { 
     get { return _command; } 
     set 
     { 
      if (_command == value) 
       return; 

      _command = value; base.RaisePropertyChanged("Command"); 
     } 
    } 

    private BitmapImage _menuIcon; 
    public BitmapImage MenuIcon 
    { 
     get { return _menuIcon; } 
     set 
     { 
      if (_menuIcon == value) 
       return; 

      _menuIcon = value; base.RaisePropertyChanged("MenuIcon"); 
     } 
    } 


    private ObservableCollection<MenuViewModel> _children; 
    public ObservableCollection<MenuViewModel> Children 
    { 
     get { return _children; } 
     set 
     { 
      _children = value; base.RaisePropertyChanged("Children"); 
     } 
    } 
} 

इस सही ढंग से गाया प्राप्त करने में किसी भी मदद की बहुत सराहना की जाएगी।

संपादित करें:

यहाँ मामले में किसी को अंतिम समाधान है यह वही समस्या भर आता है:

<DockPanel> 
    <Menu DockPanel.Dock="Top" Height="auto" ItemsSource="{Binding TopMenuItems}" > 
     <Menu.Resources> 
      <Image x:Key="MenuIconResource" Height="16" Width="16" Source="{Binding MenuIcon}" x:Shared="False" /> 
      <Style TargetType="{x:Type MenuItem}"> 
       <Setter Property="Command" Value="{Binding Command}" /> 
       <Setter Property="Header" Value="{Binding MenuText}" /> 
       <Setter Property="InputGestureText" Value="{Binding ShortcutText}" /> 
       <Setter Property="IsEnabled" Value="{Binding IsEnabled}" /> 
       <Setter Property="Icon" Value="{StaticResource MenuIconResource}" /> 
       <Setter Property="ItemsSource" Value="{Binding Children}"/> 

       <Style.Triggers> 
        <DataTrigger Binding="{Binding }" Value="{x:Null}"> 
         <Setter Property="Template" > 
          <Setter.Value> 
           <ControlTemplate> 
            <Separator Style="{StaticResource {x:Static MenuItem.SeparatorStyleKey}}" /> 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Menu.Resources> 
    </Menu> 
+1

कहाँ टेम्पलेट है अपने पदानुक्रमित डेटा टेम्पलेट में? मैं केवल आइटमकॉन्टेनर स्टाइल को – Dtex

+0

परिभाषित कर सकता हूं, मैं आपका पॉइंट देखता हूं। मैं गलत दिशा से इस पर आ रहा था, ऐसा लगता है कि न्यूनतम प्रयास के साथ मेनू को मानक रूप से देखने के लिए नीचे दी गई कस्टम शैली एक बेहतर दृष्टिकोण है? – genus

+0

@genus किसी भी विचार सेपरेटर्स का समर्थन करने के लिए इसे कैसे संपादित करें? –

उत्तर

10

अपने DataTemplate के बजाय इस प्रयास करें

<DockPanel> 
    <Menu DockPanel.Dock="Top" Height="auto" 
      ItemsSource="{Binding TopMenuItems}"> 

     <Menu.Resources> 
      <Style TargetType="{x:Type MenuItem}"> 
       <Setter Property="Command" Value="{Binding Command}" /> 
       <Setter Property="Header" Value="{Binding MenuText}" /> 
       <Setter Property="Icon"> 
        <Setter.Value> 
         <Image Source="{Binding MenuIcon}" Height="16px" Width="16px" /> 
        </Setter.Value> 
       </Setter> 
       <Setter Property="ItemsSource" Value="{Binding Children}"/> 
      </Style> 
     </Menu.Resources> 

    </Menu> 
</DockPanel> 
+0

हाँ, धन्यवाद! यह मेरी जरूरत के करीब है। यह अच्छी तरह से काम करता है सिवाय इसके कि मेनू आइकन के लिए छवि सेट प्रदर्शित नहीं हो रहा है। मैं अपने बिटमैप इमेज आइकन को नए बिटमैप इमेज (नई उरी ("पैक: // एप्लिकेशन:,/संसाधन/ओपन डॉक्यूमेंट 16.png") पर सेट कर रहा हूं) मेरे आवेदन में एक स्थिर संसाधन। कोई विचार? – genus

+0

क्या होगा यदि आप "संसाधन/OpenDocument16.png" जैसे स्ट्रिंग को वापस करते हैं? – user195275

+0

यह एक डिग्री के लिए काम करता है, उस समय जब आप क्लिक करते समय आइकन को हल करने में लगते हैं तो मेन्यू खोलने पर देरी हो जाती है। मैं शीघ्र ही एक संपादन में प्रश्न में अपना समाधान जोड़ूंगा। – genus