如何在Microsoft Dynamics 365 F&O中使用扩展技术实现即时搜索过滤器?
Absolutely! You can replicate that real-time, as-you-type filtering functionality for grouped lists using modern D365 F&O extension techniques—no outdated overlay hacks needed. This approach uses form extensions, event handlers, and dynamic query filtering, which aligns with Microsoft's recommended development practices and keeps your solution upgrade-safe.
Here's a step-by-step breakdown to implement it:
Step 1: Extend the Target Form & Add a Search Control
First, create a form extension for the form where you want the real-time filter:
- Open the Form Designer in Visual Studio and locate the base form you want to modify.
- Right-click the form and select Create extension to generate an extension project.
- Add a
StringEditcontrol to a suitable location (like the top toolbar or header section of the form). Name it something descriptive, e.g.,FilterName, and set these properties:- Label:
Filter by Name - ShowLabel:
Yes - AllowEdit:
Yes
- Label:
Step 2: Implement Real-Time Filter Logic with Event Handlers
Next, add event handlers to trigger filtering as the user types. We'll use the TextChange event for immediate updates (or add a timer delay if you want to reduce server calls):
Basic Immediate Filtering
Add this code to your form extension's class:
[FormControlEventHandler(formControlStr(YourBaseForm, FilterName), FormControlEventType::TextChange)] public static void FilterName_OnTextChange(FormControl sender, FormControlEventArgs e) { FormStringEdit filterControl = sender as FormStringEdit; FormDataSource targetDataSource = filterControl.formRun().dataSource(FormDataStr(YourBaseForm, YourDataSource)); Query query = targetDataSource.query(); QueryBuildDataSource qbds = query.dataSourceTable(tableNum(YourTargetTable)); QueryBuildRange nameRange; // Clear existing filters on the Name field qbds.clearRanges(fieldNum(YourTargetTable, Name)); // Apply new filter if input isn't empty if (filterControl.text() != '') { nameRange = qbds.addRange(fieldNum(YourTargetTable, Name)); // Use wildcard matching for partial matches nameRange.value(strFmt('*%1*', filterControl.text())); nameRange.status(RangeStatus::Open); } // Refresh the data source to update the grouped list targetDataSource.executeQuery(); }
Optional: Add a Delay to Reduce Server Load
If you want to avoid firing a query on every single keystroke (better for performance), add a TimerControl to your form extension:
- Add a
Timercontrol to the form, name itFilterTimer, and setIntervalto500(milliseconds). - Update the event handlers:
// Triggered on every keystroke—resets the timer [FormControlEventHandler(formControlStr(YourBaseForm_Extension, FilterName), FormControlEventType::TextChange)] public static void FilterName_OnTextChange(FormControl sender, FormControlEventArgs e) { FormStringEdit filterControl = sender as FormStringEdit; FormTimerControl filterTimer = filterControl.formRun().control(formControlStr(YourBaseForm_Extension, FilterTimer)); filterTimer.reset(); } // Runs the filter logic once the timer finishes counting down [FormControlEventHandler(formControlStr(YourBaseForm_Extension, FilterTimer), FormControlEventType::Tick)] public static void FilterTimer_OnTick(FormControl sender, FormControlEventArgs e) { FormTimerControl timer = sender as FormTimerControl; FormStringEdit filterControl = timer.formRun().control(formControlStr(YourBaseForm_Extension, FilterName)); FormDataSource targetDataSource = timer.formRun().dataSource(FormDataStr(YourBaseForm, YourDataSource)); Query query = targetDataSource.query(); QueryBuildDataSource qbds = query.dataSourceTable(tableNum(YourTargetTable)); QueryBuildRange nameRange; qbds.clearRanges(fieldNum(YourTargetTable, Name)); if (filterControl.text() != '') { nameRange = qbds.addRange(fieldNum(YourTargetTable, Name)); nameRange.value(strFmt('*%1*', filterControl.text())); nameRange.status(RangeStatus::Open); } targetDataSource.executeQuery(); }
Step 3: Verify Grouped List Behavior
Since the grouped list (whether it's a grid with grouping enabled or a tree control) is bound to the same form data source, calling executeQuery() will automatically refresh the grouped view to match the filtered data. If you're using a tree control, ensure its data source is linked correctly to the filtered form data source.
Key Benefits Over Overlay Techniques
- Upgrade-safe: Extensions don't modify base application code, so your changes won't be overwritten during D365 updates.
- Maintainable: Event-based logic is easier to debug and modify than overlay hacks.
- Performance: You can optimize the filtering (like adding a timer) to reduce unnecessary server requests.
内容的提问来源于stack exchange,提问作者Brian Kessler

