在WPF中,制作将特殊字符插入多个TextBox的按钮的最佳方法是什么?

时间:2012-07-16 05:58:21

标签: c# .net wpf button user-interface

如果我有多个TextBoxes和其他文本插入控件,并且我想创建一些按钮,将特殊字符插入到焦点中的哪个TextBox中,对此最好的控制是什么以及应该设置哪些属性?

按钮的要求:

  1. 按钮不会在点击时窃取焦点。
  2. 按钮可以将文本(例如特殊字符)插入任何接受键盘输入的控件中。
  3. 光标应该像用户在键盘上输入文字一样移动。
  4. 如果无法使用#2,则只需将控件限制为TextBox就足够了。

    注意:我不想让按钮不可聚焦,只是在点击时不会撬开焦点。

2 个答案:

答案 0 :(得分:0)

我不知道任何按钮在点击时没有窃取焦点,但在按钮点击事件句柄中,您可以将焦点返回给前一个所有者。如果我必须实现这一点,我将创建一个附加到所有特殊文本框的父面板的行为以及要插入一些文本的所有按钮。

  <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;
}

}

这或多或少与你所描述的有关,但它远非完美我认为这足以让你开始。

答案 1 :(得分:0)

您需要覆盖Label和TextBox的模板。

要求1和2 - 可以在Label的模板内完成,它将作为一个按钮。

要求3 - 可以在文本框的模板内完成。

这不容易......
您可能需要学习很多WPF样式,XAML和覆盖控制模板。甚至可能创建一个自定义控件。