在DataTemplate中显示和聚焦TextBox

时间:2011-11-02 20:18:53

标签: wpf textbox focus visibility

我搜索过高低,但我无法想出这个。我正在构建一个包含可编辑项目的ListBox。我DataTemplate的{​​{1}}包含ListBox.ItemTemplateTextBlock(除其他外)。 TextBox始终可见,TextBlock仅在用户双击TextBox后才可见。当用户点击列表中的其他项目时,TextBlock会再次隐藏以显示TextBox。所有这一切都很棒。看我的代码:

XAML

TextBlock

C#

<Window.Resources>
   <local:GoalCollection x:Key="goals"/>
   <DataTemplate x:Key="GoalItemTemplate" DataType="local:Goal">
      <Grid>
         <TextBlock Text="{Binding Title}"
                    MouseLeftButtonDown="TextBlock_MouseLeftButtonDown"
                    VerticalAlignment="Center"/>
         <TextBox Name="EntryBox"
                  Text="{Binding Title}"
                  Visibility="Hidden"
                  BorderBrush="{x:Null}"
                  Padding="-2,0,0,0"
                  Panel.ZIndex="1"
                  Margin="-2,0,0,0"/>
      </Grid>
   </DataTemplate>
</Window.Resources>
<Grid>
   <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition Width="2*" />
   </Grid.ColumnDefinitions>
   <ListBox Name="GoalsList"
      ItemsSource="{Binding Source={StaticResource goals}}"
      HorizontalContentAlignment="Stretch"
      ItemTemplate="{StaticResource GoalItemTemplate}"
      SelectionChanged="GoalsList_SelectionChanged" />
</Grid>

我遇到的问题是,public partial class MainWindow : Window { GoalCollection goals; public MainWindow() { InitializeComponent(); } private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject { ... } protected override void OnInitialized(EventArgs e) { base.OnInitialized(e); goals = (GoalCollection)Resources["goals"]; } private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (e.ClickCount == 2) { TextBlock tblk = sender as TextBlock; if (tblk == null) return; TextBox tbx = ((Grid)tblk.Parent).FindName("EntryBox") as TextBox; if (tbx == null) return; tbx.Visibility = Visibility.Visible; Keyboard.Focus(tbx); } } private void GoalsList_SelectionChanged(object sender, SelectionChangedEventArgs e) { ListBoxItem lbi; ContentPresenter cp; DataTemplate dt; TextBox tbx; foreach (Goal item in e.RemovedItems) { lbi = (ListBoxItem)GoalsList.ItemContainerGenerator. ContainerFromItem(item); cp = FindVisualChild<ContentPresenter>(lbi); dt = cp.ContentTemplate; tbx = (TextBox)dt.FindName("EntryBox", cp); if (tbx == null) continue; tbx.Visibility = Visibility.Hidden; } } } 会在双击后立即将焦点转移回主机TextBox。需要额外的(第三次)点击才能关注TextBox。

通过这一点,我发现ListBoxItem确实得到了关注。但它会立即失去它(尝试为TextBox事件添加处理程序并逐步执行`TextBlock_MouseLeftButtonDown()'方法)。有什么想法吗?

感谢。

2 个答案:

答案 0 :(得分:5)

我的猜测是点击事件冒泡到ListBox,它通过选择项目来处理它。

尝试将此添加到Click事件处理程序(Keyboard.Focus(tbx);之后)

e.Handled = true;

答案 1 :(得分:3)

如果要将焦点放在子元素上,请尝试使用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>