문제

저는 WPF와 MVVM을 처음 접했습니다.MVVM 파트턴에서 메뉴를 동적으로 생성하는 좋은 방법을 찾았지만 마음에 드는 것을 찾지 못해 자체 솔루션을 출시했습니다.작동하지만 어떤 이유로 메뉴의 전경(텍스트) 색상이 때때로(가끔) 올바르지 않습니다.

아래 이미지에 대한 링크를 추가했습니다.

http://img220.imageshack.us/img220/1912/badmenu.jpg (데드링크)

가장 낮은 하위 메뉴는 흰색 전경으로 올바르게 표시되지만 상위 메뉴 전경은 검은색으로 바뀌어 읽기가 거의 불가능합니다.메뉴를 하드 코딩했다면 부모의 전경색은 흰색이 될 것입니다.상위 항목 위로 마우스를 이동하면 해당 텍스트가 다시 흰색으로 바뀌고 하위 메뉴는 검은색으로 변합니다.

또한 마우스를 부모로부터 멀리 이동하면 모든 부울 속성이 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 (데드링크)

내가 뭘 잘못하고 있는지 및/또는 디스플레이 문제를 해결하는 방법에 대한 제안이 있으십니까?

도움이 되었습니까?

해결책

문제는 VM이 ​​자동으로 MenuItems에 래핑되므로 기본적으로 MenuItems의 헤더로 MenuItem이 중첩되어 있다는 것입니다.

MenuItem을 DataType으로 사용하여 VM에 데이터 바인딩(이름을 헤더로, DelegateCommands를 명령으로 등)하는 스타일을 정의하고 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>

또한 단순화를 위해 일부 명령 바인딩을 잘라냈지만 필요에 따라 다시 추가할 수 있습니다.

다른 팁

요청에 따라 여기 내 뷰 모델이 있습니다.

ViewModelbase는 Studio에서 만든 표준입니다. MainViemodel은 실험에 사용했던 테스트 메뉴를 만들기에 충분했습니다.

기본적으로 저는 광범위한 클라이언트 모음에 판매하는 일련의 앱과 함께 사용할 수있는 부모/자식 메뉴 수업을 만들기 위해 노력하고 있습니다. 각 고객이 자신의 요구에 따라 사용자 정의 가능한 메뉴 모음을 보유 할 수있는 곳과 라이센스를 구매 한 moudles를 만들고 싶습니다.

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;     }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top