2009-07-09 8 views
6
 <data:DataGridTemplateColumn Header="Name"> 
     <data:DataGridTemplateColumn.CellTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Name}"> 
      </DataTemplate> 
     </data:DataGridTemplateColumn.CellTemplate> 
     <data:DataGridTemplateColumn.CellEditingTemplate> 
      <DataTemplate> 
       <TextBox Text="{Binding Name}"> 
      </DataTemplate> 
     </data:DataGridTemplateColumn.CellEditingTemplate> 
    </data:DataGridTemplateColumn>    

Это яркий пример столбца шаблона, верно? Что может быть не так? Итак, вот что - когда пользователь перемещается по DataGrid с нажатием клавиши TAB, ему нужно дважды нажать клавишу TAB (!), Чтобы иметь возможность редактировать текст в TextBox. Как я мог сделать его редактируемым, как только пользователь получит фокус колонки, я имею в виду, даже если он только начинает печатать?WPF DataGridTemplateColumn. Я что-то упускаю?

Хорошо. Я нашел способ - в Grid.KeyUp() Я поставил код ниже:

if (Grid.CurrentColumn.Header.ToString() == "UserName") 
     { 
      if (e.Key != Key.Escape) 
      { 
       Grid.BeginEdit(); 

       // Simply send another TAB press 
       if (Keyboard.FocusedElement is Microsoft.Windows.Controls.DataGridCell) 
       { 
        var keyEvt = new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, Key.Tab) { RoutedEvent = Keyboard.KeyDownEvent }; 
        InputManager.Current.ProcessInput(keyEvt); 
       } 
      } 
     } 

ответ

8

ваша проблема связана с тем, что каждая клетка ставит его редактор в элементе управления содержимым, который первым получает фокус, то вы должны вкладке еще раз редактору. Если вы посмотрите на код DataGridTemplateColumn в методе GenerateEditingElement он вызывает метод LoadTemplateContent, который делает это:.

private FrameworkElement LoadTemplateContent(bool isEditing, object dataItem, DataGridCell cell) 
{ 
    DataTemplate template = ChooseCellTemplate(isEditing); 
    DataTemplateSelector templateSelector = ChooseCellTemplateSelector(isEditing); 
    if (template != null || templateSelector != null) 
    { 
     ContentPresenter contentPresenter = new ContentPresenter(); 
     BindingOperations.SetBinding(contentPresenter, ContentPresenter.ContentProperty, new Binding()); 
     contentPresenter.ContentTemplate = template; 
     contentPresenter.ContentTemplateSelector = templateSelector; 
     return contentPresenter; 
    } 

    return null; 
} 

посмотреть, как он создает новый контент выступающему поставить шаблон в другие люди имели дело с этим проблема разными способами, я получаю свой собственный тип столбца, чтобы справиться с этим. (Так что я не создавать дополнительный элемент или набор выступающего контента не получает фокус) В этом example они используют диспетчер фокуса, чтобы иметь дело с тем же вопросом (я нету тестировал этот код)

<tk:DataGridTemplateColumn.CellEditingTemplate> 
    <DataTemplate> 
     <Grid FocusManager.FocusedElement="{Binding ElementName=txt1}"> 
     <TextBox Name="txt1" Text="{Binding [email protected]}" 
        BorderThickness="0" GotFocus="TextBox_GotFocus"/> 
     </Grid> 
    </DataTemplate> 
</tk:DataGridTemplateColumn.CellEditingTemplate> 

Если у вас есть пользовательский элемент управления в качестве вашего редактора, то вы можете использовать шаблон с менеджером фокуса или использовать обработчик событий для события OnLoaded.

+0

работает лакомство, но это действительно некрасиво хак ... :(Я хотел бы MS найти хороший способ предоставления этот вид функциональности – David

+0

метод FocusManager хорошо работает для того, чтобы получить выбранное содержимое, вы можете также добавить получили метод фокуса:. личного недействительного StrikeTextBox_GotFocus (объект отправителя, RoutedEventArgs е) { вара TextBox = (TextBox) отправитель ; Dispatcher.BeginInvoke (новое действие (textBox.SelectAll)); } – Neil

0

Мой подход заключается в использовании TriggerAction, который устанавливает фокус на элемент шаблона, который вы хотите, когда он загружается.

Спусковой очень просто:

public class TakeFocusAndSelectTextOnVisibleBehavior : TriggerAction<TextBox> 
{ 
    protected override void Invoke(object parameter) 
    { 
     Dispatcher.BeginInvoke(
      DispatcherPriority.Loaded, 
      new Action(() => 
      { 
       AssociatedObject.Focus(); 
       AssociatedObject.SelectAll(); 
      })); 
    } 
} 

DataTemplate выглядит следующим образом:

<DataTemplate> 
    <TextBox Text="{Binding Path=Price, Mode=TwoWay}" 
       MinHeight="0" 
       Padding="1,0" 
       Height="20"> 
     <Interactivity:Interaction.Triggers> 
      <Interactivity:EventTrigger EventName="Loaded"> 
       <Behaviors:TakeFocusAndSelectTextOnVisibleBehavior /> 
      </Interactivity:EventTrigger> 
     </Interactivity:Interaction.Triggers> 
    </TextBox> 
</DataTemplate> 

Вы можете написать другие триггеры для других типов элементов.

+1

Я думаю, что для этой функции требуется dll из Expression Blend – Neil

7

Проблема, с которой вы столкнулись, заключается в том, что элемент управления (например, TextBox) внутри DataGridTemplateColumn содержится в DataGridCell. По умолчанию DataGridCell имеет функцию останова. Таким образом, причина того, что вам нужно дважды нажать TAB, чтобы сосредоточиться на вашем элементе управления TextBox. Решение состоит в том, чтобы отключить функциональность tab-stop для DataGridCell. Это можно сделать с помощью стиля для DataGridCell.

Вот решение:

<Style TargetType="{x:Type DataGridCell}"> 
    <Setter Property="KeyboardNavigation.IsTabStop" Value="False" /> 
</Style> 
3

Вот мой подход. Его очень близка к @ Налину Джаясурия, но я не хотел создавать стиль. Также это решение выбирает текст в TextBox. Во всяком случае - XAML для отверстия DataGrid выглядит так.

<DataGrid Name="TextBlockDataGrid" ItemsSource="{Binding Path=Rows}" Style="{StaticResource DefaultSettingsDataGrid}"> 
<DataGrid.Columns> 
    <DataGridTextColumn Binding="{Binding Text}" IsReadOnly="True"/> 
    <DataGridTemplateColumn Width="*"> 
     <DataGridTemplateColumn.CellStyle> 
      <Style TargetType="{x:Type DataGridCell}"> 
       <Setter Property="KeyboardNavigation.IsTabStop" Value="False"/> 
      </Style> 
     </DataGridTemplateColumn.CellStyle> 
     <DataGridTemplateColumn.CellTemplate> 
      <DataTemplate> 
       <Border BorderThickness="{Binding ErrorBorderThickness}" BorderBrush="{Binding ErrorBorderBrush}"> 
        <TextBox Text="{Binding UserText, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" 
          HorizontalAlignment="Right" 
          GotKeyboardFocus="TextBox_GotKeyboardFocus" 
          PreviewMouseDown="TextBox_PreviewMouseDown" 
          Style="{StaticResource DefaultTextBox}"/> 
       </Border> 
      </DataTemplate> 
     </DataGridTemplateColumn.CellTemplate> 
    </DataGridTemplateColumn> 
</DataGrid.Columns> 

И фоновый код.

private void TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) 
{ 
    try 
    { 
     ((TextBox)sender).SelectAll(); 
    } 
    catch (Exception ex) { GlobalDebug.debugForm.WriteText(ex); } 
} 

private void TextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
{ 
    try 
    { 
     // If its a triple click, select all text for the user. 
     if (e.ClickCount == 3) 
     { 
      ((TextBox)sender).SelectAll(); 
      return; 
     } 

     // Find the TextBox 
     DependencyObject parent = e.OriginalSource as UIElement; 
     while (parent != null && !(parent is TextBox)) 
     { 
      parent = System.Windows.Media.VisualTreeHelper.GetParent(parent); 
     } 

     if (parent != null) 
     { 
      if (parent is TextBox) 
      { 
       var textBox = (TextBox)parent; 
       if (!textBox.IsKeyboardFocusWithin) 
       { 
        // If the text box is not yet focussed, give it the focus and 
        // stop further processing of this click event. 
        textBox.Focus(); 
        e.Handled = true; 
       } 
      } 
     } 
    } 
    catch (Exception ex) { GlobalDebug.debugForm.WriteText(ex); } 
} 

Для получения дополнительной информации, посмотрите на моем блоге: http://blog.baltz.dk/post/2014/11/28/WPF-DataGrid-set-focus-and-mark-text

 Смежные вопросы

  • Нет связанных вопросов^_^