0

複数のTextBoxやその他のテキスト挿入コントロールがあり、フォーカスされているTextBoxに特殊文字を挿入するボタンを作成したい場合、これに最適なコントロールは何ですか?また、どのプロパティを設定する必要がありますか?

ボタンの要件:

  1. ボタンをクリックしてもフォーカスを奪うことはありません。
  2. ボタンは、キーボード入力を受け入れる任意のコントロールにテキスト(特殊文字など)を挿入できます。
  3. カーソルは、ユーザーがキーボードでテキストを入力したかのように移動する必要があります。

#2が不可能な場合は、コントロールをTextBoxのみに制限するだけで十分です。

注:ボタンのフォーカスを解除したくないのは、クリックしたときにフォーカスを奪わないようにするためだけです。

4

2 に答える 2

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

}

これはあなたが説明したことを多かれ少なかれ行いますが、それは完璧にはほど遠いです。私はあなたが始めるのに十分だと思います。

于 2012-07-16T07:32:11.880 に答える
0

LabelとTextBoxのテンプレートをオーバーライドする必要があります。

要件1および2-ボタンとして機能するラベルのテンプレート内で実行できます。

要件3-テキストボックスのテンプレート内で実行できます。

簡単ではありません...
多くのWPFスタイル、XAML、およびコントロールテンプレートのオーバーライドを学ぶ必要があるかもしれません。たぶんカスタムコントロールを作成することさえあります。

于 2012-07-16T07:33:04.117 に答える