首页 文章

在WPF中关注DataTemplate

提问于
浏览
1

我正在寻找的行为是在ListView中选择一个Item会导致聚焦第一个可聚焦的visualchild .

问题:ItemsControler中的datatemplated数据没有获得初始焦点 . 在下面的示例中,有4个字符串,然后通过Datatemplate填充到TextBox中 .

例:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:sys="clr-namespace:System;assembly=mscorlib" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <Grid>
      <ListView>
         <ListView.Resources>
            <DataTemplate DataType="{x:Type sys:String}" >
               <TextBox Width="100" Text="{Binding Mode=OneWay}"/>
            </DataTemplate>
         </ListView.Resources>
         <ListView.ItemsSource>
            <x:Array Type="{x:Type sys:String}">
               <sys:String>test</sys:String>
               <sys:String>test</sys:String>
               <sys:String>test</sys:String>
               <sys:String>test</sys:String>
            </x:Array>
         </ListView.ItemsSource>
      </ListView>
   </Grid>
</Window>

我已经尝试了一些组合

FocusManager.FocusedElement="{Binding ElementName=[...]}"

毫无意义地说:没有成功 . 任何人如果没有遍历c#中的可视树,我怎么能得到我想要的东西?应该可以做到这一点,不是吗?

2 回答

  • 1

    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>
    
  • 3

    在C#中使用绑定语法将不起作用,因为这是在XAML中描述绑定的方式 . 它可能会创建一个 System.Windows.Data.Binding 的新实例,并将其属性设置为与您在XAML中设置的相同,但我不确定您能够绑定到哪个 ElementName 才能使其正常工作 .

    我能想到的唯一其他选项是为 SelectionChanged 事件添加处理程序,并手动设置焦点,但这听起来不像您想要的解决方案 .

    经过进一步检查,我不认为可以使用绑定解决方案 . FocusManager.FocusedElementIInputElement ,其中没有任何与绑定相关的成员 . 我认为您需要遍历可视树以找到可聚焦的第一个对象 . 这样的事情应该有效:

    // Event handler for the ListBox.SelectionChanged event
    private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        ListBox listBox = sender as ListBox;
        ItemContainerGenerator = generator.listBox.ItemContainerGenerator;
        ListBoxItem selectedItem =
            (ListBoxItem)generator.ContainerFromIndex(listBox.SelectedIndex);
        IInputElement firstFocusable = FindFirstFocusableElement(selectedItem);
        firstFocusable.Focus();
    }
    
    private IInputElement FindFirstFocusableElement(DependencyObject obj)
    {
        IInputElement firstFocusable = null;
    
        int count = VisualTreeHelper.GetChildrenCount(obj);
        for(int i = 0; i < count && null == firstFocusable; i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(obj, i);
            IInputElement inputElement = child as IInputElement;
            if(null != inputElement && inputElement.Focusable)
            {
                firstFocusable = inputElement;
            }
            else
            {
                firstFocusable = FindFirstFocusableElement(child);
            }
        }
    
        return firstFocusable;
    }
    

相关问题