Показать и сфокусировать TextBox в DataTemplate - PullRequest
3 голосов
/ 03 ноября 2011

Я искал все выше и ниже, но не могу понять это.Я строю ListBox, в котором есть редактируемые элементы.У меня есть DataTemplate для ListBox.ItemTemplate, который содержит (помимо прочего) TextBlock и TextBox.TextBlock всегда виден, а TextBox виден только после того, как пользователь дважды щелкнет по TextBlock.Когда пользователь щелкает другой элемент в списке, TextBox снова скрывается, чтобы отобразить TextBlock.Все это прекрасно работает.См. Мой код:

XAML

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

C #

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 немедленно переключает фокус обратно на хостListBoxItem после двойного щелчка.Дополнительный (третий) щелчок необходим для фокусировки на TextBox.

Прослеживая это, я обнаружил, что TextBox действительно получает фокус.Но затем он сразу же теряет его (попробуйте добавить обработчик для события TextBox.LostKeyboardFocus и пройти и выйти из метода `TextBlock_MouseLeftButtonDown () ').Есть идеи?

Спасибо.

Ответы [ 2 ]

5 голосов
/ 03 ноября 2011

My думаю, - это то, что событие click поднимается до ListBox и обрабатывает его, выбирая элемент.

Попробуйте добавить это в свой обработчик событий Click (после Keyboard.Focus(tbx);)

e.Handled = true;
3 голосов
/ 10 августа 2012

Если вы хотите сфокусировать дочерний элемент, попробуйте 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>
...