Desative o menu de contexto em algumas células DatGrid WPF
-
27-09-2019 - |
Pergunta
Eu defini um datagrid como este ::
<cc:PEDataGrid AutoGenerateColumns="False"
ItemsSource="{Binding Rows}"
Width="Auto"
PreviewMouseRightButtonDown="PEGrid_PreviewMouseRightButtonDown"
Loaded="CommonPEGrid_Loaded">
<wpfkit:DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Cut" />
<MenuItem Header="Copy"/>
<MenuItem Header="Paste"/>
</ContextMenu>
</wpfkit:DataGrid.ContextMenu>
</cc:PEDataGrid>
Isso mostra o ContextMenu em todas as células quando o clique com o botão direito é feito.
Quero desativar o menu de contexto para todas as células, exceto cabeçalhos e também no cabeçalho para obter alguma condição. (Eu não quero usar DataGridHeaderTyle por causa de outros problemas que não quero explicar aqui.)
Eu defini um manipulador para o visualizeMouSoRightButtondown no datagrid e no manipulador, estou tentando fazer algo assim ::
private void PEGrid_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
DependencyObject depObj = (DependencyObject)e.OriginalSource;
while ((depObj != null) && !(depObj is DataGridColumnHeader))
{
depObj = VisualTreeHelper.GetParent(depObj);
}
if (depObj == null)
{
return;
}
if (depObj is DataGridColumnHeader)
{
//some condition here which says whether contextmenu is required on this header
(depObj as DataGridColumnHeader).ContextMenu = null;
//the above line is not working!!!!
}
else
{
(depObj as DataGridCell).ContextMenu = null;
//the above line not working!!!!
}
}
Eu quero saber onde estou dando errado !! Por favor me ajude a respeito disso. Também me orie para fazer de uma maneira melhor se estiver atingindo minha exigência de uma maneira errada :)
Solução
Ei, eu resolvi :: meu código modificado é o seguinte :::
private void PEGrid_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
DependencyObject depObj = (DependencyObject)e.OriginalSource;
while ((depObj != null) && !(depObj is DataGridColumnHeader))
{
depObj = VisualTreeHelper.GetParent(depObj);
}
if (depObj == null)
{
return;
}
if (depObj is DataGridColumnHeader)
{
dg.ContextMenu.Visibility = Visibility.Visible; //works
}
else
{
dg.ContextMenu.Visibility = Visibility.Collapsed; //works
}
}
Outras dicas
Eu acho que esta versão é muito mais rápida e você não precisa definir a visibilidade do menu de contexto. Basta cancelar o evento de clique se o clique estivesse no cabeçalho da coluna.
private void PEGrid_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
var depObj = (DependencyObject)e.OriginalSource;
while ((depObj != null) && !(depObj is DataGridColumnHeader))
{
depObj = VisualTreeHelper.GetParent(depObj);
}
if (depObj is DataGridColumnHeader)
{
e.Handled = true;
}
}
Eu tenho RichTextBox no DataGridCell que não é o elemento visualtree. Meu código:
private void dgLog_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
FrameworkContentElement fce = e.OriginalSource as FrameworkContentElement;
DependencyObject depObj = e.OriginalSource as DependencyObject;
DataGridCell dgc = null;
DataGridRow dgr = null;
try
{
while (fce != null && !(fce is DataGridCell))
{
depObj = fce.Parent;
fce = depObj as FrameworkContentElement;
}
while (depObj != null && !(depObj is DataGridRow))
{
if (depObj is DataGridCell)
dgc = depObj as DataGridCell;
depObj = VisualTreeHelper.GetParent(depObj);
}
if (depObj == null)
return;
dgr = depObj as DataGridRow;
if (((LogRecord)dgr.Item).SourceType == "FileMessage" && dgc.Column.DisplayIndex == 1)
dgLog.ContextMenu = cm_dgLog;
else
dgLog.ContextMenu = null;
}
catch (Exception ex)
{
MessageBox.Show(...);
TraceHelper.TraceError(ex, GetType());
}
}//private void dgLog_PreviewMouseRightButtonDown
Logrecord é o tipo de datagridcolumn.item
private void dgLog_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
FrameworkContentElement fce = e.OriginalSource as FrameworkContentElement;
DependencyObject depObj = e.OriginalSource as DependencyObject;
DataGridCell dgc = null;
DataGridRow dgr = null;
try
{
while (fce != null && !(fce is DataGridCell))
{
depObj = fce.Parent;
fce = depObj as FrameworkContentElement;
}
while (depObj != null && !(depObj is DataGridRow))
{
if (depObj is DataGridCell)
dgc = depObj as DataGridCell;
depObj = VisualTreeHelper.GetParent(depObj);
}
if (depObj == null)
return;
dgr = depObj as DataGridRow;
if (((LogRecord)dgr.Item).SourceType == "FileMessage" && dgc.Column.DisplayIndex == 1)
dgLog.ContextMenu = cm_dgLog;
else
dgLog.ContextMenu = null;
}
catch (Exception ex)
{
MessageBox.Show(...);
TraceHelper.TraceError(ex, GetType());
}
}//private void dgLog_PreviewMouseRightButtonDown
Desculpe. Primeiro tentativa não foi tão boa.