2013-06-19 2 views
1

У меня есть UserControl с Button, внутри которого открывается ContextMenu при нажатии левой кнопкой мыши. Я пытаюсь передать UserControl родительский Window в качестве параметра в команду ContextMenu, чтобы закрыть это окно, но безрезультатно. Я пробовал все с RelativeSource и PlacementTarget, но параметр всегда равен нулю. Я знаю, что ContextMenu не является частью родительского окна VisualTree. В настоящее время я придерживаюсь такого подхода, но он не работает.WPF UserControl - привязка родительского окна как параметр команды к ContextMenu MenuItem

<Grid x:Name="LayoutRoot"> 
     <Button 
      HorizontalAlignment="Left" 
      Margin="0" 
      Style="{DynamicResource ButtonStyle1}" 
      VerticalAlignment="Top" 
      Width="120" 
      Height="25" 
      Content="Dashboard Menu" 
      TextElement.FontWeight="Bold" 
      Foreground="AliceBlue"    
      > 

      <!--Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={ x:Type Window}}}"--> 
      <Button.ContextMenu> 
       <ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}" > 
        <MenuItem Header="Open Log Viewer" Command="{StaticResource openLogViewer}" /> 
        <Separator /> 
        <MenuItem Header="Exit" Command="{StaticResource exit}" CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=Window}}"/> 
       </ContextMenu> 
      </Button.ContextMenu> 
     </Button> 
    </Grid> 

Команда является Реферировано команда определена в UserControl.Resources:

<my:CommandReference x:Key="exit" Command="{Binding Exit}" /> 

и это Execute часть срабатывает, но параметр всегда нулевой. Итак, мой вопрос в том, как правильно связать родительское окно как CommandParameter из MenuItem. Любая помощь приветствуется, потому что эта вещь беспокоит меня почти два дня.

ответ

1

Правильный путь здесь не передать родительский Window VM, как CommandParameter. Если это MVVM, вы должны использовать метод Messenger (MVVM Light)/EventAggregator (Prism) для отправки сообщения в код кода Window, когда команда запускается, чтобы закрыть его.

Ссылка на Window на виртуальной машине просто неверна.

Просто для справки, что вы пытаетесь сделать "может быть сделано"

что-то вроде:

<Grid x:Name="LayoutRoot"> 
    <Button HorizontalAlignment="Left" 
      Margin="0" 
      Style="{DynamicResource ButtonStyle1}" 
      VerticalAlignment="Top" 
      Width="120" 
      Height="25" 
      Content="Dashboard Menu" 
      TextElement.FontWeight="Bold" 
      Foreground="AliceBlue" 
      Tag="{Binding RelativeSource={RelativeSource FindAncestor, 
                 AncestorType={x:Type Window}}}"> 
    <Button.ContextMenu> 
     <ContextMenu> 
     <MenuItem Header="Open Log Viewer" Command="{StaticResource openLogViewer}" /> 
     <Separator /> 
     <MenuItem Command="{StaticResource exit}" 
        CommandParameter="{Binding PlacementTarget.Tag, 
              RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" 
        Header="Exit" /> 
... 

Update:

Download Link

При выполнении «Выход "от ContextMenu вы должны увидеть Sender Object: MvvmLight16.MainWindow в своем выходном Windo ш. Этот вывод отправляется с виртуальной машины.

+0

Спасибо за объяснение, но это первый подход, который я пробовал, и он не работает. Я знаю, что я нарушаю шаблон MVVM, когда передаю родительское окно в виртуальную машину, но я не использую ни один из наборов MVVM. – wannjanjic

+0

@wannjanjic Я обновил свой ответ с помощью ссылки для загрузки к образцу, который использует подход, который я сказал, и он отлично подходит для меня. Хорошо, если вы не используете инструментарий MVVM, возможно, вам стоит подумать об использовании одного из них, кроме разрыва MVVM. Скорее не может также использовать MVVM tbh. – Viv

+0

@wannjanjic oh и удалить 'DataContext = {{Binding PlacementTarget, RelativeSource = {RelativeSource Self}}" 'из вашего' ContextMenu'. Не знаете, зачем вам это понадобилось. – Viv