代码之家  ›  专栏  ›  技术社区  ›  herzmeister

我可以将按键之类的事件传递给Silverlight中的另一个控件吗?

  •  1
  • herzmeister  · 技术社区  · 14 年前

    我能把按键之类的事件传递给 银光 ?

    假设我在一个自定义控件中,该控件包含 Textbox 和A Treeview .

    我在听 Key 事件 TextBox . 当用户按下 向上箭头 箭头向下 钥匙,我要 树形图 表现得好像是它自己收到了那个事件,也就是说,它应该向上或向下移动当前选择。用户不应该失去对 文本框 不过这样他们就可以继续打字了。

    这可能吗?我不想在树视图上手动设置选择,因为它不容易 上移选择() 下移选择() 方法,因此我必须复制该功能,特别是当树被数据绑定并按需加载节点时,该功能并不那么简单。

    3 回复  |  直到 10 年前
        1
  •  1
  •   Page    14 年前

    也许你可以考虑使用 Mediator Design Pattern 为了达到这个目的?

        2
  •  1
  •   Martin    10 年前

    我只能想出两种方法来“推进”关键事件:

    方法:在自己的代码中注册关键事件处理程序和处理事件,并通过 properties , methods , extensions (不管怎样 API 由目标控件提供)。 这是可行的,但它基本上是重新实现其他人已经编写的东西-在目标控件中-并且您总是有可能忘记一个角落的情况。

    从目标控件继承并将输入文本框添加到 ControlTemplate : 当您的控件与现有控件非常相似时,您可以诚实地说“myfoo是一个sometargetcontrol”(然后无论如何,您都可能希望提供 DependencyProperties 对于更进一步的自定义(只是目标控件类中已经存在的内容的副本),应该完全使用继承。 你的 TextBox 不会设置 ArrowUp ArrowDown 关键事件 handled ,因此继承的密钥处理代码将处理它们并正确地操作选择。

        3
  •  0
  •   herzmeister    14 年前

    同时,我通过创建 MoveSelectionUp() MoveSelectionDown() 上的扩展方法 TreeView . 我从工具箱的控制代码中的一些私有方法复制了实现,并对私有方法或受保护的方法进行了一些细微的更改。多亏了工具包中提供的所有扩展方法,现在不再那么困难了。

    因为它很大程度上不是我的,所以如果未来的访客偶然发现同样的问题,我在此提供下面的代码。

    不过,我不想回答这个问题,因为我仍然想更一般地知道,事件是否可以在dependencyobject框架中转发。

    树状延伸 :

    using System;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    
    static public class TreeViewExtensions
    {
        static public void SetSelectedContainerIfValid(this TreeView self, TreeViewItem itm)
        {
            Contract.Requires(self != null);
    
            if (itm != null)
            {
                self.SetSelectedContainer(itm);
            }
        }
    
        static public void MoveSelectionUp(this TreeView self)
        {
            Contract.Requires(self != null);
    
            var itm = self.GetSelectedContainer();
            if (itm == null)
            {
                self.SetSelectedContainerIfValid(self.GetContainers().LastOrDefault());
            }
            else
            {
                self.SetSelectedContainerIfValid(itm.GetContainerAbove());
            }
        }
    
        static public void MoveSelectionDown(this TreeView self)
        {
            Contract.Requires(self != null);
    
            var itm = self.GetSelectedContainer();
            if (itm == null)
            {
                self.SetSelectedContainerIfValid(self.GetContainers().FirstOrDefault());
            }
            else
            {
                self.SetSelectedContainerIfValid(itm.GetContainerBelow());
            }
        }
    }
    

    TreeView项目扩展 :

    using System;
    using System.Diagnostics.Contracts;
    using System.Windows;
    using System.Windows.Controls;
    
    static public class TreeViewItemExtensions
    {
        static public TreeViewItem GetContainerBelow(this TreeViewItem self)
        {
            return TreeViewItemExtensions.GetContainerBelow(self, true);
        }
    
        /// <summary>
        /// Find the next focusable TreeViewItem below this item.
        /// </summary>
        /// <param name="recurse">
        /// A value indicating whether the item should recurse into its child
        /// items when searching for the next focusable TreeViewItem.
        /// </param>
        /// <returns>The next focusable TreeViewItem below this item.</returns>
        static public TreeViewItem GetContainerBelow(this TreeViewItem self, bool recurse)
        {
            Contract.Requires(self != null);
    
            // Look for the next item in the children of this item (if allowed)
            if (recurse && self.IsExpanded && self.HasItems)
            {
                TreeViewItem item = self.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem;
                if (item != null)
                {
                    return item.IsEnabled ?
                        item :
                        item.GetContainerBelow(false);
                }
            }
    
            // Look for the next item in the siblings of this item
            ItemsControl parent = self.GetParentTreeViewItem() as ItemsControl ?? self.GetParentTreeView();
            if (parent != null)
            {
                // Get the index of this item relative to its siblings
                TreeViewItem item = null;
                int index = parent.ItemContainerGenerator.IndexFromContainer(self);
                int count = parent.Items.Count;
    
                // Check for any siblings below this item
                while (index++ < count)
                {
                    item = parent.ItemContainerGenerator.ContainerFromIndex(index) as TreeViewItem;
                    if (item != null && item.IsEnabled)
                    {
                        return item;
                    }
                }
    
                // If nothing else was found, try to find the next sibling below
                // the parent of this item
                TreeViewItem parentItem = self.GetParentTreeViewItem();
                if (parentItem != null)
                {
                    return parentItem.GetContainerBelow(false);
                }
            }
    
            return null;
        }
    
        /// <summary>
        /// Find the last focusable TreeViewItem contained by this item.
        /// </summary>
        /// <returns>
        /// The last focusable TreeViewItem contained by this item.
        /// </returns>
        static public TreeViewItem GetLastContainer(this TreeViewItem self)
        {
            Contract.Requires(self != null);
    
            TreeViewItem item = self;
            TreeViewItem lastItem = null;
            int index = -1;
    
            // Walk the children of the current item
            while (item != null)
            {
                // Ignore any disabled items
                if (item.IsEnabled)
                {
                    // If the item has no children, it must be the last
                    if (!item.IsExpanded || !item.HasItems)
                    {
                        return item;
                    }
    
                    // If the item has children, mark it as the last known
                    // focusable item so far and walk into its child items,
                    // starting from the last item and moving toward the first
                    lastItem = item;
                    index = item.Items.Count - 1;
                }
                else if (index > 0)
                {
                    // Try searching for the previous item's sibling
                    index--;
                }
                else
                {
                    // Stop searching if we've run out of children
                    break;
                }
    
                // Move to the item's previous sibling
                item = lastItem.ItemContainerGenerator.ContainerFromIndex(index) as TreeViewItem;
            }
    
            return lastItem;
        }
    
        /// <summary>
        /// Find the previous focusable TreeViewItem above this item.
        /// </summary>
        /// <returns>
        /// The previous focusable TreeViewItem above this item.
        /// </returns>
        static public TreeViewItem GetContainerAbove(this TreeViewItem self)
        {
            Contract.Requires(self != null);
    
            ItemsControl parent = self.GetParentTreeViewItem() as ItemsControl ?? self.GetParentTreeView();
            if (parent == null)
            {
                return null;
            }
    
            // Get the index of the current item relative to its siblings
            int index = parent.ItemContainerGenerator.IndexFromContainer(self);
    
            // Walk the previous siblings of the item to find a focusable item
            while (index-- > 0)
            {
                // Get the sibling
                TreeViewItem item = parent.ItemContainerGenerator.ContainerFromIndex(index) as TreeViewItem;
                if (item != null && item.IsEnabled)
                {
                    // Get the last focusable descendent of the sibling
                    TreeViewItem last = item.GetLastContainer();
                    if (last != null)
                    {
                        return last;
                    }
                }
            }
    
            return parent as TreeViewItem;
        }
    }