如何使 WPF DataGridCell 只读?
我知道您可以将整个 DataGrid 或整个列设置为只读(IsReadOnly = true)。然而,在单元格级别,此属性仅准备就绪。但我确实需要这种级别的粒度。有一篇博客介绍了在过去 DataGrid 是公共领域时通过更改源代码来将 IsReadOnly 添加到行中,但现在我没有 DataGrid 的源代码。有什么解决方法?
禁用单元格(IsEnabled = false)几乎可以满足我的需要。但问题是您甚至无法单击禁用的单元格来选择行(我有完整的行选择模式)。
编辑:由于没有人回答这个问题,所以我想这不是一个容易解决的问题。这是一个可能的解决方法:使单元格不可编辑。唯一的问题是单击单元格不会选择该行。我刚刚注意到,当单击禁用的单元格时,DataGrid 的 MouseDown 或 MouseUp 事件仍然会被触发。在此事件处理程序中,如果我可以找出它单击的行,我可以以编程方式选择该行。但是,我无法弄清楚如何从 DataGrid.InputHitTest 中找到底层行。有人可以给我一些提示吗?
I understand you can make the whole DataGrid or a whole column readyonly (IsReadOnly = true). However, at cell level this property is ready only. But I do need this level of granularity. There is blog about adding IsReadOnly to a row by changing the source code in old days when DataGrid was public domain, but now I don't have source code for DataGrid. What's workaround?
Making cell disabled (IsEnabled=false) almost meets my need. But the problem is that you can't even click the disabled cell to select the row (I have full row selection mode).
EDIT: Since nobody has responded to this question, so I guess it's not an easy fix. Here is a possible workaround: Make the cell uneditable. The only problem is that clicking the cell doesn't select the row. I just noticed that MouseDown or MouseUp event of the DataGrid is still fired when the disabled cell is clicked. In this event handler, if I could figure out the row it clicked, I could select the row programmatically. However, I couldn't figure out how to find the underlying row from DataGrid.InputHitTest
. Can somebody please give me some tip?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
获取 DataGrid 的可选只读文本单元格的一种方法是使用模板和样式,如下所示:
对于 CS 后端:
One way of getting selectable, read-only text cells for DataGrid is to use template and style like this:
And for CS backend:
您可以使用更简单的数据模板来完成此操作。
...
You can do this with a simpler data template.
...
就我而言,我使用的是
DataGridTextColumn
。我在Style
中的ContentPresenter
上设置了IsEnabled
属性,如下所示,它工作正常In my case I was using
DataGridTextColumn
. I set theIsEnabled
property onContentPresenter
inStyle
as follows and it works fine我的解决方案是使用绑定到 DataGridTemplateColumn 和转换器。
和转换器:
My solution is to use binding to the DataGridTemplateColumn with converter.
and the converter:
这有点晚了,但是,我也在研究这个问题,这些解决方案运行良好,但我需要一些不同的东西,我做了以下操作,它的工作原理与我想要的和问题所寻找的完全一样。
我本质上希望能够进入单元格的编辑模式,并使所有其他模板和命令逻辑相同,但无法编辑单元格。
所有这些问题的解决方案是在 DataGridCell 样式中将 TextBox.IsReadOnly 属性设置为 true 并处理初始 keydown 事件
和后面的以下代码以停止初始编辑
希望这会有所帮助。
This is a bit late but, I was looking into this as well, these solutions work well but I needed something a little different, I did the following and it works exactly like I wanted and what the question is looking for.
I essentially I wanted to be able to enter edit mode for the cell and have all that other templates and command logic the same while not being able to edit the cell.
The solution for all this is to set the TextBox.IsReadOnly property to true in the DataGridCell Style and to handle the initial keydown event
and the following code behind to stop the initial edit
Hopefully this is helpful.
基于@sohum 评论,在这里您可以使用标记为答案的响应的简化版本。
您稍后可以将其用作附加属性行为。
Based on @sohum comment, here you can use simplified version of the response marked as answer.
You can use it later as Attached Property Behaviour.
对我来说,最简单的解决方案是在
EditingElementStyle
内设置TextBox
的样式。For me, the most simple solution was to style the
TextBox
inside theEditingElementStyle
.我通过在单元格中设置底层对象(例如 CheckBox)解决了这个问题 -
IsHitTestVisible = false;
Focusable = false;
"row " 是一个
DataGridRow
。IsHitTestVisible=false
表示您无法通过鼠标点击/选择/操作底层对象,但您仍然可以选择DataGridCell
。Focusable=false
表示您无法使用键盘选择/操作底层对象。这给人一种ReadOnly
单元格的错觉,但您仍然可以选择该单元格,并且我确定DataGrid
是否设置为SelectionMode=FullRow 然后单击“只读”单元格将选择整行。
I've solved this problem in my application by setting the underlying object in the cell (eg. CheckBox) -
IsHitTestVisible = false;
Focusable = false;
"row" is a
DataGridRow
.IsHitTestVisible=false
means that you can't click/select/manipulate the underlying object via mouse, but you can still select theDataGridCell
.Focusable=false
means that you can't select/manipulate the underlying object with the keyboard. This gives the illusion of aReadOnly
cell, but you can still select the cell and I'm sure if theDataGrid
is set up toSelectionMode=FullRow
then clicking the "read only" cell will select the entire row.您可能认为可以绑定
DataGridCell.IsReadOnly
上的一个属性,例如,像这样使用 XAML:
不幸的是,这不起作用,因为该属性不可写。
接下来,您可能会尝试拦截并停止鼠标事件,但这不会阻止用户使用 F2 键进入编辑模式。
我解决此问题的方法是侦听 DataGrid 上的
PreviewExecutedEvent
,然后有条件地将其标记为已处理。例如,通过将与此类似的代码添加到我的 Window 或 UserControl 的构造函数(或另一个更合适的地方):
通过这样做,单元格仍然可以聚焦和选择。
但用户将无法进入编辑模式,除非您的模型项允许给定行进入编辑模式。
使用 DataGridTemplateColumn 不会带来性能成本或复杂性。
There is a property on
DataGridCell.IsReadOnly
that you might think you can bind to,e.g. using XAML like this:
Unfortunantly this won't work because this property is not writable.
Next you might attempt to intercept and stop mouse events, but this won't prevent the user from entering edit mode using the F2 key.
The way I sloved this was by listening for the
PreviewExecutedEvent
on the DataGrid and then conditionally flagging it as handled.E.g. by adding code similar to this to the constructor of my Window or UserControl (or another more suitable place):
By doing it like this the cells are still focusable and selectable.
But the user will not be able to enter edit mode unless your model items allow it for the given row.
And you will not suffer the performance costs or complexities by using the DataGridTemplateColumn.
我遇到了同样的问题,单元格在某些行中应该是只读的,但在其他行中则不是。这是一种解决方案:
其想法是在两个模板之间动态切换
CellEditingTemplate
,一个与CellTemplate
中的模板相同,另一个用于编辑。这使得编辑模式的行为与非编辑单元格完全相同,尽管它处于编辑模式。以下是执行此操作的一些示例代码,请注意,此方法需要
DataGridTemplateColumn
:首先,定义两个用于只读和编辑单元格的模板:
然后定义一个带有附加
ContentPresenter
的数据模板code> 层并使用Trigger
来切换ContentPresenter
的ContentTemplate
,这样上面两个模板就可以通过IsEditable 动态切换绑定:
HTH
I've encountered the same problem, the cell should be read-only in some rows but not in the others. Here is a workaround solution:
The idea is to dynamically switch the
CellEditingTemplate
between two templates, one is the same as the one in theCellTemplate
, the other is for editing. This makes the edit mode acts exactly the same as the non-editing cell although it is in edit mode.The following is some sample code for doing this, notice that this approach requires
DataGridTemplateColumn
:First, define two templates for read-only and editing cells:
Then define a data template with additional
ContentPresenter
layer and useTrigger
to switch theContentTemplate
of theContentPresenter
, so the above two templates can be switched dynamically by theIsEditable
binding:HTH
经过大量搜索和实验后,使用 IsTabStop = False 和 Focusable = False 最适合我。
After much searching and experimentation using IsTabStop = False and Focusable = False works best for me.