2009-07-09 62 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,它需要按下TAB兩次,才能在文本框來編輯文本(!)。一旦用戶獲得專欄專注,我如何才能使其可編輯,我的意思是即使他剛開始打字?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

您的問題從每個細胞把它的編輯器,其中首先接收焦點的內容控制的事實,莖,那麼你必須標籤再次向編輯。如果你看一下在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; 
} 

看看它是如何創建一個新的內容展示器把模板中的其他人都處理了這個問題以各種方式出現,我推導出自己的列類型來處理這個問題。 (所以我不創建一個額外的元素,或將內容展示給未獲得焦點)在此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> 

如果你有一個用戶控件編輯器,那麼你可以使用該模式爲重點經理或使用一個事件處理程序裝載的事件。

+0

工作的一種享受,但是這確實是一個醜陋的黑客... :(我希望微軟會發現提供的一個很好的方式這種功能 – David 2011-04-11 15:30:00

+0

FocusManager方法運作良好爲了獲得所選內容,您還可以添加一個獲得的焦點方法: private void StrikeTextBox_GotFocus(object sender,RoutedEventArgs e) var textBox =(TextBox)sender ; Dispatcher.BeginInvoke(new Action(textBox.SelectAll)); } – Neil 2011-11-18 14:18:36

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> 

你可以寫其他觸發其他元素類型。

7

您所面臨的問題是,DataGridTemplateColumn內的控制(例如,文本框)包含一個DataGridCell內。默認情況下,DataGridCell具有製表位功能。因此,必須打兩次TAB以獲得焦點到TextBox控件的原因。解決方法是禁用DataGridCell的製表位功能。這可以通過DataGridCell的樣式完成。

這裏的解決方案:

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

這裏是我的做法。它非常接近@Nalin Jayasuriya的答案,但我不想創造一種風格。此解決方案也可選擇文本框中的文本。無論如何 - 洞DataGrid的XAML看起來像這樣。

<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