I have a requirement to put a XamDataGrid into edit mode when it receives focus. The idea is that when a user tabs into a XamDataGrid I find the first editable cell and make it the active cell. Then I put the grid into edit mode. Sounds simple - of course it isn't.
My first attempt added a GotFocus handler but I found it was also being called as the user navigated around within the grid. Each cell raises a GotFocus event as it receives focus and, by default, this is bubbled up to the grid. There is no way to know why the event is being called (even OriginalSource isn't reliable).
Infragistics has a class called Infragistics.Windows.Helpers.FocusWithinManager. Their documentation is obtuse and the example is overly complex. It turns out to be quite simple to use (but not as simple as an event would be).
Start a new Visual Studio project (I'm using 2022). Make it a WPF App (.Net Framework) C# project and call it EditOnFocus.
We will start by subclassing the XamDataGrid. Add references to InfragisticsWPF4, InfragisticsWPF4.Editors, and InfragisticsWPF4.DataPresenter.
Add a new class called EditOnFocusXamDataGrid that inherits XamDataGrid. It needs a static constructor that registers a FocusWithinManager.
FocusWithinManager.RegisterType(typeof(EditOnFocusXamDataGrid), new System.Windows.PropertyChangedCallback(OnIsFocusWithinChanged));
The FocusWithinManager will call OnIsFocusWithinChanged whenever the focus changes. Let's write that method.
XamDataGrid g = (XamDataGrid)d;
CellValuePresenter cvp;
// We're a XamDataGrid and we just got focus
if (g != null && !Convert.ToBoolean(e.OldValue) && Convert.ToBoolean(e.NewValue))
// Find the first editable cell
foreach (DataRecord r in g.Records.Where(r => r is DataRecord).Cast<DataRecord>())
foreach (Cell c in r.Cells)
cvp = CellValuePresenter.FromCell(c);
if (cvp != null && cvp.IsEditingAllowed)
// Start editing the cell
g.ActiveCell = c;
g.ExecuteCommand(DataPresenterCommands.StartEditMode);
return;
}
}
}
}
This demonstration will display a text box, our new EditOnFocusXamDataGrid and another text box stacked on top of each other. When you tab from the top text box, the XamDatGrid will go into edit mode. The same will happen when you back-tab from the bottom text box.
Here's the XAML.
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:igDP="http://infragistics.com/DataPresenter"
xmlns:local="clr-namespace:EditOnFocus"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="450" Width="800">
<StackPanel Orientation="Vertical">
<TextBox Width="100"/>
<local:EditOnFocusXamDataGrid DataSource="{Binding Items}" Height="100">
<local:EditOnFocusXamDataGrid.FieldLayoutSettings>
<igDP:FieldLayoutSettings AutoGenerateFields="False"/>
</local:EditOnFocusXamDataGrid.FieldLayoutSettings>
<local:EditOnFocusXamDataGrid.FieldLayouts>
<igDP:FieldLayout>
<igDP:FieldLayout.Fields>
<igDP:TextField Label="Code" Name="Code" AllowEdit="True" Width="60"/>
<igDP:TextField Label="Description" Name="Description" AllowEdit="False" Width="*"/>
</igDP:FieldLayout.Fields>
</igDP:FieldLayout>
</local:EditOnFocusXamDataGrid.FieldLayouts>
</local:EditOnFocusXamDataGrid>
<TextBox Width="100"/>
</StackPanel>
</Window>
Here's the code behind.
using System.Windows;
namespace EditOnFocus
public class cItem
{
public String Code { get; set; }
public partial class MainWindow : Window
public List<cItem> Items { get; set; } = new List<cItem> {
public MainWindow()
InitializeComponent();
}
}
}
When you run the demonstration, click in the top text box and hit tab. You can see the grid goes into edit mode as soon as it receives focus.
Shift-tabbing from the bottom text box works too.
No comments:
Post a Comment