С#: Как избежать проверки TreeNode из события двойного щелчка
Итак, у меня есть TreeView в приложении формы Windows С#. Мне нужно, чтобы некоторые узлы были "заблокированы", чтобы они не могли быть проверены (или не отмечены) на основе параметра.
Теперь я делаю следующее:
private void tv_local_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
TNode node = (TNode)e.Node;
//if a part node, cancel the action.
if (node.Type == "Part") {
e.Cancel = true;
}
//if a locked node, cancel the action
if (node.Locked == true) {
e.Cancel = true;
}
}
Этот код отлично работает с одним щелчком флажка, но если пользователь дважды нажимает на этот флажок, он по-прежнему проверяет/отменяет выбор.
Я попытался сыграть с событием nodeMouseDoubleClick, но это действительно не помогает, поскольку я не могу отменить событие...
Есть ли какие-либо идеи, как отменить событие двойного щелчка на node?... или что-нибудь еще?
Благодаря
Ответы
Ответ 1
Это ошибка в TreeView, я думаю (http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/9d717ce0-ec6b-4758-a357-6bb55591f956/). Вам нужно подклассифицировать древовидное представление и отключить сообщение двойного щелчка, чтобы исправить его. Вот так:
public class NoClickTree : TreeView
{
protected override void WndProc(ref Message m)
{
// Suppress WM_LBUTTONDBLCLK
if (m.Msg == 0x203) { m.Result = IntPtr.Zero; }
else base.WndProc(ref m);
}
};
Конечно, если вы это сделаете, вы больше не сможете использовать метафору двойного щелчка в древовидном представлении для других вещей (например, дважды щелкните по node, чтобы запустить страницу свойств или что-то еще).
Ответ 2
Если вы хотите, чтобы ваш двойной щелчок на самом деле переключил флажок, попробуйте:
protected override void WndProc(ref Message m)
{
// Filter WM_LBUTTONDBLCLK when we're showing check boxes
if (m.Msg == 0x203 && CheckBoxes)
{
// See if we're over the checkbox. If so then we'll handle the toggling of it ourselves.
int x = m.LParam.ToInt32() & 0xffff;
int y = (m.LParam.ToInt32() >> 16) & 0xffff;
TreeViewHitTestInfo hitTestInfo = HitTest(x, y);
if (hitTestInfo.Node != null && hitTestInfo.Location == TreeViewHitTestLocations.StateImage)
{
OnBeforeCheck(new TreeViewCancelEventArgs(hitTestInfo.Node, false, TreeViewAction.ByMouse));
hitTestInfo.Node.Checked = !hitTestInfo.Node.Checked;
OnAfterCheck(new TreeViewEventArgs(hitTestInfo.Node, TreeViewAction.ByMouse));
m.Result = IntPtr.Zero;
return;
}
}
base.WndProc(ref m);
}
Ответ 3
Мне это удалось с помощью следующего кода, который предотвращает проверку корневых узлов:
private void MyTreeView_MouseUp(object sender, MouseEventArgs e)
{
// HACK: avoid to check root nodes (mr)
var node = ((TreeView)sender).GetNodeAt(new Point(e.X, e.Y));
if (node != null && node.Parent == null)
BeginInvoke(new MouseEventHandler(TreeView_MouseUpAsync), sender, e);
}
private void TreeView_MouseUpAsync(object sender, MouseEventArgs e)
{
if (IsDisposed)
return;
var node = ((TreeView)sender).GetNodeAt(new Point(e.X, e.Y));
node.Checked = false;
}
Ответ 4
Попробуйте расширить класс TreeNode и добавить логическое свойство, которое поддерживает надлежащее checkedState. Таким образом, когда кто-то дважды щелкнет node, вы можете reset вернуть состояние node к значению, хранящемуся в свойстве. Возможно, будет более элегантное решение, но это лучшее, что я могу придумать.