WPF对话框中AvalonEditor的Find按钮绑定搜索(MVVM方式)
在WPF MVVM模式下通过按钮触发AvalonEditor的搜索功能
我懂你的需求——已经给AvalonEditor装好了SearchPanel,Ctrl+F能正常弹出搜索框,现在想在MVVM架构下,点击窗口上的Find按钮也能触发这个搜索功能,不想用传统的代码隐藏事件对吧?下面给你具体的实现步骤和代码,完全符合MVVM的规范:
第一步:先实现通用的RelayCommand(如果项目里还没有的话)
MVVM里需要自定义命令来绑定按钮动作,先写一个基础的RelayCommand类,后面ViewModel会用到:
public class RelayCommand : ICommand { private readonly Action<object> _execute; private readonly Func<object, bool> _canExecute; public event EventHandler CanExecuteChanged { add => CommandManager.RequerySuggested += value; remove => CommandManager.RequerySuggested -= value; } public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; } public bool CanExecute(object parameter) { return _canExecute?.Invoke(parameter) ?? true; } public void Execute(object parameter) { _execute(parameter); } }
第二步:创建ViewModel并添加搜索命令
ViewModel里定义一个FindCommand,用来触发搜索面板的显示。我们把TextEditor实例作为命令参数传递,这样ViewModel不需要直接耦合视图元素,完全符合MVVM的分离原则:
using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit.Search; using System.ComponentModel; using System.Windows.Input; public class MainWindowViewModel : INotifyPropertyChanged { public ICommand FindCommand { get; } public MainWindowViewModel() { FindCommand = new RelayCommand(ExecuteFindCommand); } private void ExecuteFindCommand(object parameter) { // 从命令参数中获取TextEditor实例 if (parameter is TextEditor textEditor) { // 获取之前已经安装好的SearchPanel实例 var searchPanel = SearchPanel.GetSearchPanel(textEditor.TextArea); // 打开搜索面板,效果和按下Ctrl+F完全一致 searchPanel.Open(); } } // MVVM必备的INotifyPropertyChanged实现 public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
第三步:修改XAML,绑定ViewModel和命令
把原来的代码隐藏式CommandBinding替换成ViewModel的命令绑定,同时把TextEditor作为命令参数传递给按钮,还要给窗口设置DataContext:
<Window x:Class="YourNamespace.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" xmlns:local="clr-namespace:YourNamespace" Title="MainWindow" Height="450" Width="800"> <!-- 将ViewModel设置为窗口的数据上下文 --> <Window.DataContext> <local:MainWindowViewModel /> </Window.DataContext> <Grid> <StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Left"> <Button Name="FindButton" Content="Find" Margin="2" Style="{DynamicResource ButtonFooter_Style}" <!-- 绑定ViewModel中的FindCommand --> Command="{Binding FindCommand}" <!-- 把TextEditor实例作为命令参数传递 --> CommandParameter="{Binding ElementName=textEditor}"> </Button> <avalonEdit:TextEditor Grid.Row="2" Grid.Column="1" Name="textEditor" FontFamily="Consolas" FontSize="10pt" SyntaxHighlighting="XML" ShowLineNumbers="True" > </avalonEdit:TextEditor> </StackPanel> </Grid> </Window>
第四步:确认TextEditor的SearchPanel已正确安装
你原来的TextEditor构造函数已经完成了这一步,完全没问题,再确认下:
public TextEditor() : this(new TextArea()) { Search.SearchPanel.Install(this.TextArea); }
补充说明
- 我们通过
SearchPanel.GetSearchPanel(textEditor.TextArea)获取之前安装好的搜索面板实例,而不是重新创建,这样能保证和Ctrl+F触发的是同一个面板,搜索状态也会同步。 - 如果你的项目已经有了类似RelayCommand的实现(比如Prism的DelegateCommand),可以直接用自己的,不用重复编写。
内容的提问来源于stack exchange,提问作者user1910087
相关产品推荐
相关产品推荐

