我了解您可以将整个 DataGrid 或整个列设为仅就绪 (IsReadOnly = true)。但是,在单元级别,此属性仅准备就绪。但我确实需要这种粒度级别。在过去 DataGrid 是公共(public)领域时,有一篇关于通过更改源代码将 IsReadOnly 添加到一行的博客,但现在我没有 DataGrid 的源代码。有什么解决方法?
禁用单元格(IsEnabled=false)几乎可以满足我的需要。但问题是您甚至无法单击禁用的单元格来选择行(我有全行选择模式)。
编辑:由于没有人回答这个问题,所以我想这不是一个容易解决的问题。这是一个可能的解决方法:使单元格不可编辑。唯一的问题是单击单元格不会选择行。我刚刚注意到,当单击禁用的单元格时,仍会触发 DataGrid 的 MouseDown 或 MouseUp 事件。在这个事件处理程序中,如果我能找出它单击的行,我可以以编程方式选择该行。但是,我不知道如何从 DataGrid.InputHitTest
中找到底层行.有人可以给我一些提示吗?
最佳答案
DataGridCell.IsReadOnly
上有一处房产你可能认为你可以绑定(bind)到,
例如像这样使用 XAML:
<!-- Won't work -->
<DataGrid Name="myDataGrid" ItemsSource="{Binding MyItems}">
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<Setter Property="IsReadOnly" Value="{Binding MyIsReadOnly}" />
</Style>
</DataGrid.Resources>
<!-- Column definitions... -->
</DataGrid>
不幸的是,这不起作用,因为该属性不可写。
接下来您可能会尝试拦截和停止鼠标事件,但这不会阻止用户使用 F2 键进入编辑模式。
我解决这个问题的方法是收听
PreviewExecutedEvent
在 DataGrid 上,然后有条件地将其标记为已处理。例如。通过将类似于此的代码添加到我的 Window 或 UserControl (或其他更合适的地方)的构造函数中:
myDataGrid.AddHandler(CommandManager.PreviewExecutedEvent,
(ExecutedRoutedEventHandler)((sender, args) =>
{
if (args.Command == DataGrid.BeginEditCommand)
{
DataGrid dataGrid = (DataGrid) sender;
DependencyObject focusScope = FocusManager.GetFocusScope(dataGrid);
FrameworkElement focusedElement = (FrameworkElement) FocusManager.GetFocusedElement(focusScope);
MyRowItemModel model = (MyRowItemModel) focusedElement.DataContext;
if (model.MyIsReadOnly)
{
args.Handled = true;
}
}
}));
通过这样做,单元格仍然是可聚焦和可选择的。
但是除非您的模型项允许给定行,否则用户将无法进入编辑模式。
通过使用 DataGridTemplateColumn,您不会受到性能成本或复杂性的影响。
关于wpf - 如何使 WPF DataGridCell 只读?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3843331/