WPF CommandParameter не обновляется при установке в контекстном меню - PullRequest
1 голос
/ 13 сентября 2010

У меня есть окно wpf с несколькими элементами управления текстового поля.Мне нужно применить общий стиль, который бы применял контекстное меню к каждому элементу управления, и я определил его глобально следующим образом:

<ContextMenu x:Key="textBoxMenu">
        <Separator/>
        <MenuItem Header="Affirm" 
                  Command="{Binding Path=AffirmCommand}" 
                  CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TextBox},AncestorLevel=1}}"/>                      
    </ContextMenu>

    <Style TargetType="{x:Type TextBox}" x:Key="TextBoxAffirmMenuStyle">
        <Setter Property="ContextMenu" Value="{DynamicResource textBoxMenu}" />
    </Style>

Я использовал команду для выполнения соответствующего метода в зависимости от цели объекта.контекстное меню, которое в данном случае является текстовым полем.

Чтобы однозначно идентифицировать элементы управления, я установил свойство «Tag» каждого элемента управления с уникальной строкой, и у меня есть доступ к этому тегу из параметра команды, который являетсяустановить для целевого текстового поля сам элемент управления.

private bool CanAffirmExecute(object param)
        {

            string columnName = (param as FrameworkElement).Tag as string;

            if (this.CheckIsAffirmed(columnName))
                return true;
            else
                return false;
        }

private void AffirmExecute(object param)
        {

            string columnName = (param as FrameworkElement).Tag as string;

            this.Affirm(columnName);
        }

Проблема с этим заключается в том, что после того, как параметр команды установлен на конкретный элемент управления, он не изменится в последующих операциях контекстного меню при щелчке правой кнопкой мыши на другомконтроль.параметр Command остается статическим и получает только значение тега, установленное в первом элементе управления.

Как я могу заставить это работать, чтобы я мог получить доступ к каждому из значений тегов элементов управления, используя команду?

спасибо.

1 Ответ

0 голосов
/ 14 сентября 2010

ContextMenu находится в корне своего собственного визуального дерева, поэтому любая привязка с использованием RelativeSource.FindAncestor не проходит мимо ContextMenu.

Обходной путь - использовать двухэтапную привязку со свойством PlacementTarget следующим образоми проанализировать параметр объекта в методе OnAffirmCommand (object obj) для управления вашим поведением.В этом случае объект является фактическим TextBox.

Вот определение контекстного меню:

<Window.Resources>
  <ContextMenu x:Key="textBoxMenu">
    <Separator/>
    <MenuItem Header="Affirm"  
          Command="{Binding Path=AffirmCommand}"  
          CommandParameter="{Binding PlacementTarget.Tag, 
                                     RelativeSource={RelativeSource FindAncestor, 
                                     AncestorType={x:Type ContextMenu}}}"/>
   </ContextMenu>

   <Style TargetType="{x:Type TextBox}" x:Key="TextBoxAffirmMenuStyle">
       <Setter Property="ContextMenu" Value="{StaticResource textBoxMenu}" />
   </Style>
</Window.Resources>

Вот текстовые поля:

<Grid>
    <Grid.RowDefinitions>
       <RowDefinition/>
       <RowDefinition/>
       <RowDefinition/>
    </Grid.RowDefinitions>

    <TextBox Grid.Row="0" ContextMenu="{StaticResource textBoxMenu}" Tag="{Binding RelativeSource={RelativeSource Self}}" Text="text in box 1"/>
    <TextBox Grid.Row="1" ContextMenu="{StaticResource textBoxMenu}" Tag="{Binding RelativeSource={RelativeSource Self}}" Text="text in box 2"/>
     <TextBox Grid.Row="2" ContextMenu="{StaticResource textBoxMenu}" Tag="{Binding RelativeSource={RelativeSource Self}}" Text="text in box 3"/>
</Grid>

Воткод команды от модели представления:

public class MainViewModel : ViewModelBase
{
  public ICommand AffirmCommand { get; set; }

  public MainViewModel()
  {
     AffirmCommand = new DelegateCommand<object>(OnAffirmCommand, CanAffirmCommand);
  }

  private void OnAffirmCommand(object obj)
  {
  }

  private bool CanAffirmCommand(object obj)
  {
     return true;
  }
}
...