如果我有多个文本框和其他文本插入控件,并且我想创建一些按钮来将特殊字符插入到任何一个TextBox所关注的焦点中,那么对此的最佳控制和应设置的属性是什么?在WPF中,制作将特殊字符插入多个文本框的按钮的最佳方法是什么?
的按钮要求:
- 按钮按下时不偷焦点。
- 按钮可以将文本(例如特殊字符)插入任何接受键盘输入的控件。
- 光标应该像用户在键盘上输入文字一样移动。
如果#2是不可能的,则仅将控件限制为文本框即可。
注意:我不想让按钮不可调焦,只有这样才不会在点击时窃取焦点。
如果我有多个文本框和其他文本插入控件,并且我想创建一些按钮来将特殊字符插入到任何一个TextBox所关注的焦点中,那么对此的最佳控制和应设置的属性是什么?在WPF中,制作将特殊字符插入多个文本框的按钮的最佳方法是什么?
的按钮要求:
如果#2是不可能的,则仅将控件限制为文本框即可。
注意:我不想让按钮不可调焦,只有这样才不会在点击时窃取焦点。
我不知道有任何按钮在点击时不会窃取焦点,但在按钮单击事件处理中,您可以将焦点返回给以前的所有者。如果我必须实现这个,我会创建一个附加到所有特殊文本框的父面板以及插入一些文本的所有按钮的行为。
<StackPanel>
<i:Interaction.Behaviors>
<local:TextBoxStateTracker/>
</i:Interaction.Behaviors>
<TextBox />
<Button Content="description" Tag="?" />
</StackPanel>
为了简化示例,我将要插入到文本框中的文本插入到Tag属性中。
public class TextBoxStateTracker : Behavior<Panel>
{
private TextBox _previouslySelectedElement;
private int _selectionStart;
private int _selectionLength;
protected override void OnAttached()
{
//after control and all its children are created find textboxes and buttons
AssociatedObject.Initialized += (x, y) =>
{
var textBoxElements = FindChildren<TextBox>(AssociatedObject);
foreach (var item in textBoxElements)
{
item.LostFocus += new RoutedEventHandler(item_LostFocus);
}
var buttons = FindChildren<Button>(AssociatedObject);
foreach (var item in buttons)
{
item.Click += new RoutedEventHandler(item_Click);
}
};
}
private void item_Click(object sender, RoutedEventArgs e)
{
if (_previouslySelectedElement == null) return;
//simply replace selected text in previously focused textbox with whatever is in tag property
var button = (Button)sender;
var textToInsert = (string)button.Tag;
_previouslySelectedElement.Text = _previouslySelectedElement.Text.Substring(0, _selectionStart)
+ textToInsert +
_previouslySelectedElement.Text.Substring(_selectionStart + _selectionLength);
_previouslySelectedElement.Focus();
_previouslySelectedElement.SelectionStart = _selectionStart + textToInsert.Length;
}
private void item_LostFocus(object sender, RoutedEventArgs e)
{
//this method is fired when textboxes loose their focus note that this
//might not be fired by button click
_previouslySelectedElement = (TextBox)sender;
_selectionStart = _previouslySelectedElement.SelectionStart;
_selectionLength = _previouslySelectedElement.SelectionLength;
}
public List<TChild> FindChildren<TChild>(DependencyObject d)
where TChild : DependencyObject
{
List<TChild> children = new List<TChild>();
int childCount = VisualTreeHelper.GetChildrenCount(d);
for (int i = 0; i < childCount; i++)
{
DependencyObject o = VisualTreeHelper.GetChild(d, i);
if (o is TChild)
children.Add(o as TChild);
foreach (TChild c in FindChildren<TChild>(o))
children.Add(c);
}
return children;
}
}
这确实你所描述的更多或更少,但它是远远不够完善,我认为这是足以让你开始。
您需要重写Label和TextBox的模板。
要求1和2 - 可以在标签的模板内完成,该标签将充当按钮。
要求3-可以在文本框的模板内完成。
这并不容易......
您可能需要学习很多WPF样式,XAML和重写控件模板。甚至可能创建一个自定义控件。
小蛮力在每个接受键盘输入的控件上注册丢失的焦点事件,该事件保存对UI键盘控件的引用。 – Paparazzi 2012-07-16 14:20:26