2009-07-09 7 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>    

テンプレートの列の例は間違いありません。何が間違っているのでしょうか? ここでは、ユーザーがTABキーを押しながらDataGridをナビゲートするときに、TextBoxのテキストを編集できるようにするためにTabキーを2回(!)押す必要があります。ユーザーが列のフォーカスを取得するとすぐに編集可能にすることができます。入力を開始したばかりであってもどうですか?WPF DataGridTemplateColumn。何か不足していますか?

は、あなたの問題は、各セルが最初にフォーカスを受け取るコンテンツコントロールにそのエディタを置くことに起因
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

、その後、あなたはタブに持っている:私は以下のコードを入れて()Grid.KeyUpに - 私は方法を見つけましたもう一度エディタに戻ってください。あなたはGenerateEditingElement方法でDataGridTemplateColumnのコードを見ている場合には、これを行う方法の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; 
} 

は、それがテンプレートを置くための新しいコンテンツプレゼンターを作成する方法を見て他の人がこれを扱っています。問題をさまざまな方法で解決するために、私はこのようなものに対処するために私自身の列型を派生します。あなたが持っている場合は

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

(私はこのコードをテストしたhaventは)彼らは同じ問題に対処するためにフォーカスマネージャを使用している。このexampleでは(私は、余分な要素を作成したり、フォーカスを受け取るないようにコンテンツプレゼンターを設定していけません)ユーザーコントロールをエディタとして使用する場合は、フォーカスマネージャでパターンを使用するか、OnLoadedイベントにイベントハンドラを使用できます。

+0

は御馳走を動作しますが、これは本当に醜いハックです...私は、MSが提供する素敵な方法を見つけてほしい:(機能 – David

+0

のFocusManagerメソッドのこの種はうまく機能した内容は、選択し得るために、あなたも持っフォーカス方式を追加することができます。 ます。private void StrikeTextBox_GotFocus(オブジェクト送信者、RoutedEventArgs e)の { VARテキストボックス=(テキストボックス)送信者; 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

この機能には、Expression Blendのdllが必要です – Neil

7

あなたが直面した問題は、DataGridTemplateColumn内のコントロール(TextBoxなど)がDataGridCellに含まれていることです。デフォルトでは、DataGridCellにはタブストップ機能があります。したがって、TextBoxコントロールにフォーカスを合わせるためにTabキーを2回押しなければならない理由です。解決方法は、DataGridCellのタブストップ機能を無効にすることです。これは、DataGridCellのスタイルを使用して行うことができます。

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

はここに私のアプローチです:

はここソリューションです。 @Nalin Jayasuriyaの回答に非常に近いですが、スタイルを作成したくありませんでした。また、このソリューションは、テキストボックス内のテキストを選択します。とにかく - 穴の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

関連する問題