You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF为DataGridTextColumn添加PreviewMouseDown事件实现点击弹出自定义键盘

WPF DataGrid单元格点击弹出自定义键盘实现方案

DataGridTextColumn 不属于可视化树内的元素,无法直接挂载PreviewMouseDown事件,有两种可落地的实现路径,按需选择即可。

方法1:按列挂载事件(精准控制触发键盘的列范围)

针对需要触发键盘的列,分别给只读显示态的TextBlock、编辑态的TextBox挂载事件即可,基于你提供的代码修改如下:

第一步 修改XAML代码

<DataGrid x:Name="datagridusers" 
          materialDesign:ColorZoneAssist.Background="Wheat"  
          VerticalAlignment="Top" Height="400" Margin="20 80 20 20" 
          HorizontalContentAlignment="Stretch"  
          VerticalContentAlignment="Stretch"  
          Style="{StaticResource MaterialDesignDataGrid}" 
          FontSize="15" 
          materialDesign:ScrollViewerAssist.SupportHorizontalScroll="True" 
          CanUserAddRows="False" 
          AutoGenerateColumns="False">
    <DataGrid.Columns>
        <materialDesign:DataGridTextColumn Header="USER ID" 
                                           Binding="{Binding Id}"    
                                           IsReadOnly="True">
            <DataGridTextColumn.ElementStyle>
                <Style TargetType="TextBlock">
                    <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
                    <Setter Property="TextBlock.TextAlignment" Value="Center"/>
                    <!-- 只读态文本块挂载鼠标预览事件 -->
                    <EventSetter Event="PreviewMouseDown" Handler="DataGridCell_PreviewMouseDown"/>
                </Style>
            </DataGridTextColumn.ElementStyle>
        </materialDesign:DataGridTextColumn>

        <!-- 可编辑列示例,需要同时给显示态、编辑态控件挂载事件 -->
        <materialDesign:DataGridTextColumn Header="USER NAME" Binding="{Binding UserName}">
            <DataGridTextColumn.ElementStyle>
                <Style TargetType="TextBlock">
                    <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
                    <Setter Property="TextBlock.TextAlignment" Value="Center"/>
                    <EventSetter Event="PreviewMouseDown" Handler="DataGridCell_PreviewMouseDown"/>
                </Style>
            </DataGridTextColumn.ElementStyle>
            <DataGridTextColumn.EditingElementStyle>
                <Style TargetType="TextBox">
                    <EventSetter Event="PreviewMouseDown" Handler="DataGridCell_PreviewMouseDown"/>
                </Style>
            </DataGridTextColumn.EditingElementStyle>
        </materialDesign:DataGridTextColumn>
    </DataGrid.Columns >
</DataGrid>

注意:Style必须显式声明TargetType,否则EventSetter无法匹配到对应控件的事件。

第二步 编写后台事件逻辑

// 记录当前激活的输入控件,用于自定义键盘回传输入内容
private UIElement _currentInputTarget;

private void DataGridCell_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    _currentInputTarget = sender as UIElement;
    
    // 可编辑列自动进入编辑状态
    DataGridCell clickedCell = FindVisualParent<DataGridCell>(sender as DependencyObject);
    if (clickedCell != null && !clickedCell.IsReadOnly && !clickedCell.IsEditing)
    {
        clickedCell.IsEditing = true;
        // 异步等待编辑控件加载完成后切换焦点
        Dispatcher.BeginInvoke(new Action(() =>
        {
            if (clickedCell.Content is TextBox editTb)
            {
                editTb.Focus();
                _currentInputTarget = editTb;
            }
        }), System.Windows.Threading.DispatcherPriority.Input);
    }

    // 弹出自定义键盘逻辑,以下示例基于Popup承载键盘
    if (KeyboardPopup != null)
    {
        // 定位键盘到当前单元格下方
        Point popPos = _currentInputTarget.TranslatePoint(new Point(0, _currentInputTarget.RenderSize.Height), this);
        KeyboardPopup.PlacementRectangle = new Rect(popPos.X, popPos.Y, 0, 0);
        KeyboardPopup.IsOpen = true;
    }
}

// 可视化树查找辅助方法
private static T FindVisualParent<T>(DependencyObject child) where T : DependencyObject
{
    DependencyObject parent = VisualTreeHelper.GetParent(child);
    if (parent == null) return null;
    return parent as T ?? FindVisualParent<T>(parent);
}

方法2:全局挂载事件(适合列数多、所有可编辑单元格都要触发键盘的场景)

不用给每列单独加样式,直接给DataGrid本身挂载PreviewMouseDown事件,在事件里过滤点击源即可:

XAML修改

直接在DataGrid标签上追加事件配置,其余属性保持不变:

<DataGrid x:Name="datagridusers" 
          PreviewMouseDown="Datagridusers_PreviewMouseDown">

后台逻辑

private void Datagridusers_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    // 只响应单元格内文本块、输入框的点击
    if (e.OriginalSource is not TextBlock and not TextBox) return;
    
    _currentInputTarget = e.OriginalSource as UIElement;
    // 后续进入编辑状态、弹键盘的逻辑和方法1完全一致
}

自定义键盘适配注意点

  • 自定义键盘的所有控件要设置Focusable="False",避免点击键盘按钮抢走单元格的输入焦点,导致内容无法正常写入
  • 点击键盘按键时,如果当前目标是TextBox,直接操作SelectedText属性插入/删除内容即可;如果是只读列的TextBlock,直接修改其绑定的数据源对应属性,WPF绑定机制会自动刷新UI
  • 点击DataGrid其他区域、窗口其他区域时记得关闭键盘Popup,避免遮挡界面

内容的提问来源于stack exchange,提问作者Mustafa Şan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 05:33:16