我具有包含DataTemplate TextBox。我设置上选择该模板列表框项目。

我无法将焦点设置到文本框模板。我试图打电话MyTemplate.FindName,但它与一个无效操作异常结束了:该操作是有效的仅在具有应用这个模板元素

我怎样才能访问它?

有帮助吗?

解决方案

既然你知道你想要合焦的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尚未完全被我们进入该方法时被初始化。

其他提示

我知道这是老了,但我碰到这个问题今天到底跑想出了这个决议:

由于一个项被选择时仅在加载TextBox,那就是当你想焦点设置,可以简单地处理该TextBox.Load事件并调用Focus()

有两种方法来实现这一点。

<强> 1。替换用的TextBoxDataTemplate AutoFocusTextBox

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

不要忘记你需要引用其中AutoFocusTextBox在您的.xaml文件中定义的命名空间。

<强> 2。在将DataTemplate定义该文件的代码隐藏添加处理程序。

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

无论使用哪种方法,你可以随时添加在处理其他行为,如选择的所有文本。

确定。因此,我认为我有最好的解决方案。它的工作对我来说反正。我有,我想给焦点到文本框中输入一个简单的数据模板。所述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>

Jay的第二建议是整齐 - 并且可以通过使用UIElement而非TextBox被更一般化,使得任何控制可以很容易地作出的默认值:

private void FocusControlOnLoad(object sender, RoutedEventArgs e)
{
    var uiElement = sender as UiElement;
    if(uiElement == null) return;
    uiElement.Focus();
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top