65.9K
CodeProject 正在变化。 阅读更多。
Home

用于聚焦控件的覆盖层

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (5投票s)

2008 年 9 月 24 日

CPOL

2分钟阅读

viewsIcon

21461

downloadIcon

226

这应有助于提高可用性

介绍 

我一直在思考如何提高可用性的可能性,其中一个想法是“聚焦”到一个控件上,向用户展示他/她可以在哪里进行操作。

Using the Code

使用方法非常简单。在添加了对库的引用后,只需编写如下代码:

var overlay = new Focuser.FocusOverlay<TextBox>(this.Container, this.Test);
overlay.Show();	 

要隐藏在 mouseclick 上的叠加层,您的代码应如下所示

overlay.MouseDown += new MouseButtonEventHandler((sender2, e2) =>
    {
        overlay.Hide();
        this.Test = (TextBox)overlay.CloneBack() 
    }); 

CloneBack 函数用显示在叠加层中的控件(即克隆)替换原始控件。如果您希望保留对控件所做的更改,同时在叠加层中显示它,则需要调用此函数。

重要提示:如果您有一个变量保存对控件的引用(通常情况下,如果您为控件指定了名称),则需要重新分配此变量!否则,引用将失效。

背景

叠加层是一个 Adorner,您可以在此了解更多信息。

要在 Adorner 中使用控件,必须重写 Adorner 类中的几个函数,即 VisualChildrenCountGetVisualChildMeasureOverride ArangeOverride。并且 - 您需要使用 AddLogicalChild AddVisualChild 函数设置子项。

子项不是聚焦的控件本身,而是一个包含控件的 Canvas。这是为了将控件精确地放置在其原始位置。可以这样找到绝对原始位置

var pos = this.FocusedControl.TransformToAncestor(this.Target).Transform(new Point());
 
//Subtract margin because the margin is also cloned 
pos -= new Vector(this.FocusedControlClone.Margin.Left, 
	this.FocusedControlClone.Margin.Top);  

如您所见,使用 TransformToAncestor 函数找到位置,该函数返回一个 GeneralTransforum。然后您需要从位置中减去边距,因为它也被克隆了。
要确定控件的宽度和高度,使用其 ActualWidth ActualHeight 属性。

通过定时器更新位置,以便在窗口调整大小后保持最新。您可以在演示应用程序中测试这一点。

要聚焦的控件必须是 FrameworkElement,因为该类包含 Parent 属性,该属性用于将原始控件替换为克隆。

只有当控件包含在 Panel ItemsControl 中时,这才能工作。代码如下所示

this.Canvas.Children.Remove(this.FocusedControlClone);
//Exchange control
if (this.FocusedControl.Parent is Panel)
{
    var parent = this.FocusedControl.Parent as Panel;
    parent.Children.Remove(this.FocusedControl);
    parent.Children.Add(this.FocusedControlClone);
}
else
{
    var parent = this.FocusedControl.Parent as ItemsControl;
    var index = parent.Items.IndexOf(this.FocusedControl);
    parent.Items.Remove(this.FocusedControl);
    parent.Items.Insert(index, this.FocusedControlClone);
}

//Update reference to original control
this.FocusedControl = this.FocusedControlClone; 
//Remove reference to clone, because this is the original now 
this.FocusedControlClone = null; 

关注点

克隆是以一种有趣的方式完成的,实际上是我从互联网上获得的

if (original == null)
    return null;

string s = XamlWriter.Save(original);
StringReader stringReader = new StringReader(s);
XmlReader xmlReader = XmlTextReader.Create(stringReader, new XmlReaderSettings());   

return (T)XamlReader.Load(xmlReader); 

这可能不是非常优雅,但它有效.. ;-)。

历史

  • 2008年9月24日:创建文章
© . All rights reserved.