10

DataTemplate含んでいTextBoxます。このテンプレートを選択範囲のリストボックス項目に設定しています。

テンプレートのテキスト ボックスにフォーカスを設定できません。MyTemplate.FindName を呼び出そうとしましたが、無効な操作の例外で終わります: この操作は、このテンプレートが適用されている要素に対してのみ有効です。

どうすればアクセスできますか?

4

4 に答える 4

13

これが古いことは知っていますが、今日この問題に遭遇し、最終的にこの解決策を思いつきました:

はアイテムが選択されたときにのみロードされ、フォーカスを設定するときにのみロードされるため、単純にイベントをTextBox処理して を呼び出すことができます。TextBox.LoadFocus()

これを実現するには 2 つの方法があります。

TextBox1.の を にDataTemplate置き換えますAutoFocusTextBox

public class AutoFocusTextBox : TextBox
{
    public AutoFocusTextBox()
    {
        Loaded += delegate { Focus(); }; 
    }
}

.xaml ファイルで AutoFocusTextBox が定義されている名前空間を参照する必要があることを忘れないでください。

DataTemplate2.が定義されているファイルの分離コードにハンドラーを追加します。

SomeResourceDictionary.xaml

<TextBox Text="{Binding Something, Mode=TwoWay}" Style={StaticResource ...
        Loaded="FocusTextBoxOnLoad" />

SomeResourceDictionary.xaml.cs

    private void FocusTextBoxOnLoad(object sender, RoutedEventArgs e)
    {
        var textbox = sender as TextBox;
        if(textbox == null) return;
        textbox.Focus();
    }

いずれのオプションでも、すべてのテキストを選択するなど、ハンドラーに他の動作をいつでも追加できます。

于 2010-06-25T21:43:31.000 に答える
10

TextBoxフォーカスしたいの名前を知っているので、これは比較的簡単になります。アイデアは、それ自体に適用されるテンプレートを把握することListBoxItemです。

最初にやりたいことは、選択したアイテムを取得することです:

var item = listBox1.ItemContainerGenerator.ContainerFromItem(listBox1.SelectedItem) as ListBoxItem;

次に、その名前に基づいてコントロールにフォーカスするこの小さなヘルパー関数にそれを渡すことができます。

public void FocusItem(ListBoxItem item, string name)
{
    if (!item.IsLoaded)
    {
        // wait for the item to load so we can find the control to focus
        RoutedEventHandler onload = null;
        onload = delegate
        {
            item.Loaded -= onload;
            FocusItem(item, name);
        };
        item.Loaded += onload;
        return;
    }

    try
    {
        var myTemplate = FindResource("MyTemplateKey") as FrameworkTemplate; // or however you get your template right now

        var ctl = myTemplate.FindName(name, item) as FrameworkElement;
        ctl.Focus();
    }
    catch
    {
        // focus something else if the template/item wasn't found?
    }
}

ちょっと難しいのは、アイテムがロードされるのを確実に待つことだと思います。ItemContainerGenerator.StatusChangedイベントからこれを呼び出していたので、そのコードを追加する必要がListBoxItemあり、メソッドに入るまでに完全に初期化されていない場合がありました。

于 2008-11-30T23:10:04.490 に答える
7

Ok。だから私は最善の解決策を持っていると思います。とにかくそれは私のために働いた。テキスト ボックスにフォーカスを当てたい単純なデータ テンプレートがあります。FocusManagerテキスト ボックスにフォーカスを移します。

<DataTemplate x:Key="MyDataTemplate" DataType="ListBoxItem">
    <Grid>
        <WrapPanel Orientation="Horizontal" FocusManager.FocusedElement="{Binding ElementName=tbText}">
            <CheckBox IsChecked="{Binding Path=Completed}" Margin="5" />
            <Button Style="{StaticResource ResourceKey=DeleteButtonTemplate}" Margin="5" Click="btnDeleteItem_Click" />
            <TextBox Name="tbText" 
                     Text="{Binding Path=Text}" 
                     Width="200" 
                     TextWrapping="Wrap" 
                     AcceptsReturn="True" 
                     Margin="5" 
                     Focusable="True"/>
            <DatePicker Text="{Binding Path=Date}" Margin="5"/>
        </WrapPanel>
    </Grid>
</DataTemplate>
于 2012-08-10T00:33:24.580 に答える
2

Jay の 2 番目の提案はきちんとしていて、UIElementではなくを使用することでより一般化できるTextBoxため、任意のコントロールを簡単にデフォルトにすることができます。

private void FocusControlOnLoad(object sender, RoutedEventArgs e)
{
    var uiElement = sender as UiElement;
    if(uiElement == null) return;
    uiElement.Focus();
}
于 2010-09-09T08:21:50.317 に答える