Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O ContextMenuOpening evento pode ser tratado em um aplicativo para ajustar um menu de contexto existente antes de exibir ou suprimir o menu que, de outra forma, seria exibido, definindo a propriedade Handled como true nos dados do evento. O motivo típico para definir Handled nos dados do evento é substituir o menu completamente por um novo objeto true, o que às vezes requer cancelar a operação e iniciar uma nova abertura com ContextMenu. Se você escrever manipuladores para o evento ContextMenuOpening, deverá estar ciente das questões de sincronização entre um controle ContextMenu e o serviço responsável por abrir e posicionar menus de contexto para os controles em geral. Este tópico ilustra algumas das técnicas de código para vários cenários de abertura de menu de contexto e ilustra um caso em que o problema de tempo entra em jogo.
Há vários cenários para lidar com o ContextMenuOpening evento:
Ajustando os itens de menu antes da exibição.
Substituindo todo o menu antes de ser exibido.
Suprimindo completamente qualquer menu de contexto existente e não exibindo nenhum menu de contexto.
Exemplo
Ajustando os itens de menu antes da exibição
Ajustar os itens de menu existentes é bastante simples e provavelmente é o cenário mais comum. Você pode fazer isso para adicionar ou subtrair opções de menu de contexto em resposta às informações de estado atuais em seu aplicativo ou informações de estado específicas que estão disponíveis como uma propriedade no objeto em que o menu de contexto é solicitado.
A técnica geral é obter a origem do evento, que é o controle específico que foi clicado com o botão direito do mouse, e obter a propriedade ContextMenu dele. Normalmente, você deseja verificar a Items coleção para ver quais itens de menu de contexto já existem no menu e, em seguida, adicionar ou remover novos MenuItem itens apropriados de ou para a coleção.
void AddItemToCM(object sender, ContextMenuEventArgs e)
{
//check if Item4 is already there, this will probably run more than once
FrameworkElement fe = e.Source as FrameworkElement;
ContextMenu cm = fe.ContextMenu;
foreach (MenuItem mi in cm.Items)
{
if ((String)mi.Header == "Item4") return;
}
MenuItem mi4 = new MenuItem();
mi4.Header = "Item4";
fe.ContextMenu.Items.Add(mi4);
}
Substituindo o menu inteiro antes da exibição
Um cenário alternativo é se você quiser substituir todo o menu de contexto. É claro que você também pode usar uma variação do código anterior, para remover cada item de um menu de contexto existente e adicionar novos a partir do item zero. Mas a abordagem mais intuitiva para substituir todos os itens no menu de contexto é criar um novo ContextMenu, preenchê-lo com itens e, em seguida, definir a FrameworkElement.ContextMenu propriedade de um controle como o novo ContextMenu.
A seguir está o código do manipulador simples para substituir um ContextMenu. O código faz referência a um método personalizado BuildMenu , que é separado porque é chamado por mais de um dos manipuladores de exemplo.
void HandlerForCMO(object sender, ContextMenuEventArgs e)
{
FrameworkElement fe = e.Source as FrameworkElement;
fe.ContextMenu = BuildMenu();
}
ContextMenu BuildMenu()
{
ContextMenu theMenu = new ContextMenu();
MenuItem mia = new MenuItem();
mia.Header = "Item1";
MenuItem mib = new MenuItem();
mib.Header = "Item2";
MenuItem mic = new MenuItem();
mic.Header = "Item3";
theMenu.Items.Add(mia);
theMenu.Items.Add(mib);
theMenu.Items.Add(mic);
return theMenu;
}
No entanto, se você usar esse estilo de manipulador, ContextMenuOpeningpoderá potencialmente expor um problema de tempo se o objeto em que você está definindo ContextMenu não tiver um menu de contexto pré-existente. Quando um usuário clica com o botão direito do mouse em um controle, ContextMenuOpening é gerado mesmo se o existente ContextMenu estiver vazio ou nulo. Mas, nesse caso, qualquer novo valor ContextMenu que você definir no elemento de origem chega tarde demais para ser exibido. Além disso, se o usuário clicar com o botão direito do mouse uma segunda vez e, desta vez, seu novo ContextMenu aparecer, o valor não será nulo, e o manipulador substituirá e exibirá corretamente o menu quando for executado pela segunda vez. Isso sugere duas soluções alternativas possíveis:
Garanta que ContextMenuOpening os manipuladores sempre sejam executados em controles que têm pelo menos um espaço reservado ContextMenu disponível, o qual deve ser substituído pelo código do manipulador. Nesse caso, você ainda pode usar o manipulador mostrado no exemplo anterior, mas normalmente deseja atribuir um espaço reservado ContextMenu na marcação inicial:
<StackPanel> <Rectangle Fill="Yellow" Width="200" Height="100" ContextMenuOpening="HandlerForCMO"> <Rectangle.ContextMenu> <ContextMenu> <MenuItem>Initial menu; this will be replaced ...</MenuItem> </ContextMenu> </Rectangle.ContextMenu> </Rectangle> <TextBlock>Right-click the rectangle above, context menu gets replaced</TextBlock> </StackPanel>Suponha que o valor inicial ContextMenu possa ser nulo, com base em alguma lógica preliminar. Você pode verificar ContextMenu se há nulo ou usar um sinalizador em seu código para verificar se o manipulador foi executado pelo menos uma vez. Como você pressupõe que ContextMenu está prestes a ser exibido, seu manipulador então define Handled para
truenos dados do evento. Para o ContextMenuService responsável pela exibição do menu de contexto, um valortruenos dados do evento representa uma solicitação para cancelar a exibição da combinação de menu de contexto/controle que gerou o evento.
Agora que você suprimiu o menu de contexto potencialmente suspeito, a próxima etapa é fornecer um novo e exibi-lo. Definir o novo elemento é basicamente o mesmo que o manipulador anterior: você cria um novo ContextMenu e define a propriedade FrameworkElement.ContextMenu do controle com ele. A etapa adicional é que agora você deve forçar a exibição do menu de contexto, pois você suprimiu a primeira tentativa. Para forçar a exibição, defina a Popup.IsOpen propriedade para true dentro do manipulador. Tenha cuidado ao fazer isso, pois abrir o menu de contexto no manipulador aciona o ContextMenuOpening evento novamente. Se você reenterar seu manipulador, ele se tornará infinitamente recursivo. É por isso que você sempre precisa verificar null ou usar um indicador, caso abra um menu de contexto a partir de um manipulador de eventos ContextMenuOpening.
Suprimindo qualquer menu de contexto existente e sem exibir menu de contexto
O cenário final, escrever um manipulador que suprime totalmente um menu, é incomum. Se um determinado controle não deve exibir um menu de contexto, provavelmente há maneiras mais apropriadas de garantir isso do que suprimindo o menu apenas quando um usuário o solicita. Mas se você quiser usar o manipulador para suprimir um menu de contexto e não mostrar nada, o manipulador deverá simplesmente definir Handledtrue nos dados do evento. O ContextMenuService responsável por exibir um menu de contexto verificará os dados do evento que ele acionou no controle. Se o evento tiver sido marcado Handled em qualquer lugar ao longo da rota, a ação de abertura do menu de contexto que iniciou o evento será suprimida.
void HandlerForCMO2(object sender, ContextMenuEventArgs e)
{
if (!FlagForCustomContextMenu)
{
e.Handled = true; //need to suppress empty menu
FrameworkElement fe = e.Source as FrameworkElement;
fe.ContextMenu = BuildMenu();
FlagForCustomContextMenu = true;
fe.ContextMenu.IsOpen = true;
}
}
}
Consulte também
- ContextMenu
- FrameworkElement.ContextMenu
- Visão geral dos elementos base
- Visão geral de ContextMenu
.NET Desktop feedback