我有一个数据网格,其中有一个AutoCompleteBox 我希望当我将焦点切换到包含ACB的单元格时,它会直接进入输入模式。目前我必须按回车键才能完成。 这里是代码:
<DataGrid Grid.ColumnSpan="3"
AutoGenerateColumns="False"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsSynchronizedWithCurrentItem="True"
RowHeight="30"
Grid.Column="0"
SelectionUnit="Cell"
ItemsSource="{Binding RowsToEdit, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
SelectedItem="{Binding SelectedPerson, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
b:DataGridEnterKeyBehavior.EnterKeyNexCellProperty="True"
b:DataGridEnterEditOnCellGotFocus.EnterEditOnGotFocusProperty="True" Margin="0,45,0,5" Grid.RowSpan="2"
>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Code, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, StringFormat=\{0:#\}}" Header="Code" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewKeyDown">
<gs:EventToCommand Command="{Binding HandleCellKeyDownCommand, Source={StaticResource MyViewModel}}"
PassEventArgsToCommand="True"
/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGridTextColumn>
<DataGridTemplateColumn Header="Name" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Nom}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<!--FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}" -->
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<controls:AutoCompleteBox
x:Name="acb2"
Text="{Binding Nom, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding Names,Source={StaticResource MyViewModel}}"
SelectedItem="{Binding Path=SelectedPerson, Source={StaticResource MyViewModel}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ValueMemberBinding="{Binding Nom}"
Style="{StaticResource acbStyle}"
ItemTemplate="{StaticResource AutoCompleteBoxItemTemplate}"
>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<gs:EventToCommand Command="{Binding SelectionChangedCommand, Source={StaticResource MyViewModel}}"
CommandParameter="{Binding Path=SelectedPerson, Source={StaticResource MyViewModel}}"
/>
</i:EventTrigger>
</i:Interaction.Triggers>
</controls:AutoCompleteBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding Adresse, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Adresse" />
</DataGrid.Columns>
</DataGrid>
//Behaviors
//Behavior for passing automatically in edit mode when cell get focus
public static class DataGridEnterEditOnCellGotFocus
{
public static readonly DependencyProperty EnterEditOnGotFocusProperty =
DependencyProperty.RegisterAttached("EnterEditOnGotFocus",
typeof(bool),
typeof(DataGridEnterEditOnCellGotFocus),
new UIPropertyMetadata(false, ProcessCellGotFocusEnter));
public static bool GetEnterEditOnGotFocusProperty(DependencyObject obj)
{
return (bool)obj.GetValue(EnterEditOnGotFocusProperty);
}
public static void SetEnterEditOnGotFocusProperty(DependencyObject obj, bool value)
{
obj.SetValue(EnterEditOnGotFocusProperty, value);
}
private static void ProcessCellGotFocusEnter(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DataGrid dg = (d as DataGrid);
if (dg != null)
{
if ((bool)e.NewValue)
dg.GotFocus += dg_GotFocus;
else
dg.GotFocus -= dg_GotFocus;
}
}
private static void dg_GotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() == typeof(DataGridCell))
{
DataGridCell source = e.OriginalSource as DataGridCell;
DataGrid grd = (DataGrid)sender;
grd.BeginEdit(e);
Control control = GetFirstChildByType<Control>(source);
if (control != null)
{
control.Focus();
}
}
}
//Behaviors for moving from cell to another with entre key
public static class DataGridEnterKeyBehavior
{
public static readonly DependencyProperty EnterKeyNexCellProperty =
DependencyProperty.RegisterAttached("EnterKeyNexCell",
typeof(bool),
typeof(DataGridEnterKeyBehavior),
new UIPropertyMetadata(false, ProcessEnterKeyDown));
public static bool GetEnterKeyNexCellProperty(DependencyObject obj)
{
return (bool)obj.GetValue(EnterKeyNexCellProperty);
}
public static void SetEnterKeyNexCellProperty(DependencyObject obj, bool value)
{
obj.SetValue(EnterKeyNexCellProperty, value);
}
private static void ProcessEnterKeyDown(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DataGrid dg = (d as DataGrid);
if (dg != null)
{
if ((bool)e.NewValue)
dg.PreviewKeyDown += dg_PreviewKeyDownDatagrid;
else
dg.PreviewKeyDown -= dg_PreviewKeyDownDatagrid;
}
}
private static void dg_PreviewKeyDownDatagrid(object sender, KeyEventArgs e)
{
DataGrid dg = (sender as DataGrid);
var uiElement = e.OriginalSource as UIElement;
if (e.Key == Key.Enter && uiElement != null)
{
e.Handled = true;
dg.SelectedCells.Clear();
uiElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
dg.BeginEdit();
}
}
}
ViewModel
public class MyViewModel : ObservableObject
{
ObservableCollection<Person> _names = null;
ObservableCollection<Person> _rowsToEdit = null;
public ObservableCollection<Person> RowsToEdit
{
get { return _rowsToEdit; }
set
{
_rowsToEdit = value;
RaisePropertyChanged("RowsToEdit");
}
}
RelayCommand _loadClients;
RelayCommand _showSelectedPerson;
RelayCommand<Person> _selectchangedcommand;
RelayCommand<KeyEventArgs> _handleCellKeyDown;
Person _selectedPerson;
public Person SelectedPerson
{
get { return _selectedPerson; }
set
{
_selectedPerson = value;
RaisePropertyChanged("SelectedPerson");
}
}
public ObservableCollection<Person> Names
{
get { return _names; }
set
{
_names = value;
RaisePropertyChanged("Names");
}
}
public RelayCommand LoadClientCommand
{
get
{
if (_loadClients == null)
_loadClients = new RelayCommand(LoadCommandExecute);
return _loadClients;
}
}
private void LoadCommandExecute()
{
LoadClients();
List<Person> ll = new List<Person>(1);
ll.Add(new Person(0, "", ""));
RowsToEdit = new ObservableCollection<Person>(ll);
}
public void LoadClients()
{
List<Person> ll = new List<Person>(8);
ll.Add(new Person(1, "AAAAAAA", "Adresse1"));
ll.Add(new Person(2, "AABBBBB", "Adresse 2"));
ll.Add(new Person(3, "AAACCCC", "Adresse3"));
ll.Add(new Person(4, "BBBBHHHH", "Adresse4"));
ll.Add(new Person(5, "BBBCGGFR", "Adresse5"));
ll.Add(new Person(6, "JJJJJHHGYGH", "Adresse6"));
ll.Add(new Person(7, "HHHHHHHHGGG", "Adresse7"));
ll.Add(new Person(8, "AAAAHHGBV", "Adresse8"));
Names = new ObservableCollection<Person>(ll);
}
public RelayCommand ShowSelectedPersonCommand
{
get
{
if (_showSelectedPerson == null)
_showSelectedPerson = new RelayCommand(ShowSelectedPersonCommandExecute);
return _showSelectedPerson;
}
}
private void ShowSelectedPersonCommandExecute()
{
if (SelectedPerson != null)
MessageBox.Show(SelectedPerson.Nom);
else
MessageBox.Show("No sslections.");
}
public RelayCommand<Person> SelectionChangedCommand
{
get
{
if (_selectchangedcommand == null)
_selectchangedcommand = new RelayCommand<Person>(SelectionChangedCommandExecute);
return _selectchangedcommand;
}
}
private void SelectionChangedCommandExecute(Person SelectedPerson)
{
/*if (SelectedPerson != null)
MessageBox.Show(SelectedPerson.Code.ToString());
else
MessageBox.Show("Pas de sélection.");
*/
}
}
答案 0 :(得分:0)
见下面的例子。它使用名为dgrdInvoice的DataGrid。
private void dgrdInvoice_PreviewGotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource is DataGridCell)
{
DataGridCell cell = (DataGridCell)e.OriginalSource;
Debug.WriteLine(cell.ToString());
RoutedEventHandler gotFocusHandler = new RoutedEventHandler(DataGridCell_GotFocus);
cell.GotFocus -= gotFocusHandler;
cell.GotFocus += gotFocusHandler;
KeyEventHandler previewKeyDownHandler = new KeyEventHandler(DataGridcell_PreviewKeyDown);
cell.PreviewKeyDown -= previewKeyDownHandler;
cell.PreviewKeyDown += previewKeyDownHandler;
}
}
void DataGridCell_GotFocus(object sender, RoutedEventArgs e)
{
DataGridCell cell = (DataGridCell)sender;
dgrdInvoice.CurrentCell = new DataGridCellInfo((DataGridCell)sender);
dgrdInvoice.BeginEdit();
Debug.WriteLine("got focus" + cell.ToString());
e.Handled = true;
}
void DataGridcell_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
DataGridCell cell = (DataGridCell)sender;
DataGridCellsPresenter cellsPresenter = (DataGridCellsPresenter)DataGridCellsPresenter
.ItemsControlFromItemContainer(cell);
int cellCount = cellsPresenter.Items.Count;
int currCellIndex = dgrdInvoice.CurrentColumn.DisplayIndex;
DataGridRow rowContainer = (DataGridRow)DataGridCellsPresenter.ContainerFromElement(dgrdInvoice, cell);
DataGridCell nextCell;
if (e.Key == Key.Enter || e.Key == Key.Escape)
{
if (currCellIndex < cellCount - 1)
{
nextCell = GetCell(dgrdInvoice, rowContainer, currCellIndex + 1); // get next cell
}
else
{
currCellIndex = -1;
nextCell = GetCell(dgrdInvoice, GetNextRow(dgrdInvoice, rowContainer), currCellIndex + 1); // get next cell
}
if(e.Key == Key.Escape)
{
dgrdInvoice.CancelEdit();
}
e.Handled = true;
nextCell.Focus();
dgrdInvoice.BeginEdit();
}
}
#region DataGrid Navigation Helper
public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T)
return (T)child;
else
{
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
public static DataGridRow GetNextRow(System.Windows.Controls.DataGrid dataGrid, DataGridRow currRow)
{
DataGridRow nextRow = null;
for (int i = 0; i < dataGrid.Items.Count; ++i)
{
DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(i);
if (row.Equals(currRow))
{
nextRow = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(i + 1);
if (nextRow.IsNewItem)
nextRow = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(0);
break;
}
}
return nextRow;
}
public static DataGridCell GetCell(System.Windows.Controls.DataGrid dataGrid, DataGridRow rowContainer, int column)
{
if (rowContainer != null)
{
DataGridCellsPresenter presenter = FindVisualChild<DataGridCellsPresenter>(rowContainer);
if (presenter == null)
{
/* if the row has been virtualized away, call its ApplyTemplate() method
* to build its visual tree in order for the DataGridCellsPresenter
* and the DataGridCells to be created */
rowContainer.ApplyTemplate();
presenter = FindVisualChild<DataGridCellsPresenter>(rowContainer);
}
if (presenter != null)
{
DataGridCell cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
if (cell == null)
{
/* bring the column into view
* in case it has been virtualized away */
dataGrid.ScrollIntoView(rowContainer, dataGrid.Columns[column]);
cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
}
return cell;
}
}
return null;
}
#endregion
答案 1 :(得分:0)
最后我找到了一个解决方案,也许还有其他更好的解决方案。 问题在于在ACB中选择控制“文本”。所以改变行为如下解决问题。这里代码:
private static void dg_GotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() == typeof(DataGridCell))
{
// Starts the Edit on the row;
DataGridCell source = e.OriginalSource as DataGridCell;
DataGrid grd = (DataGrid)sender;
grd.BeginEdit(e);
source.IsEditing = true;
Control control = GetFirstChildByType<Control>(source);
if (control != null)
{
//Here i Check if control is an ACB, if it is
//Try to access to Control "Text" inside it and that's all
if (control.GetType() == typeof(AutoCompleteBox))
{
control = GetFirstChildByType<Control>(control);
}
}
if (control != null)
control.Focus();
e.Handled = true;
}
}