Consider the following DataGrid having three columns:
考虑下面的DataGrid有三个列:
When ever the age is -1 the corresponding cell gets disabled.
当年龄为-1时,相应的细胞就会被禁用。
Ideally it shall not be possbile for the user to change the disabled cell value. However consider the user is in row 1 and the keyboard focus is in the corresponding cell of column Age, and presses enter, now the user types any number and the disabled cell get that value! Is this a desired behaviour? How can I avoid this behaviour?
在理想的情况下,用户不应该改变禁用的单元格值。但是考虑到用户在第1行,键盘焦点在相应的列年龄单元格中,按enter,现在用户输入任何数字,被禁用的单元格就会得到那个值!这是一种期望的行为吗?我怎样才能避免这种行为呢?
To replicate issue:
复制的问题:
- Select cell in row 1 of Age column
- 选择年龄列的第一行中的单元格
- Press enter
- 按回车键
- Type a number
- 输入一个数字
Reproducible code:
可复制的代码:
XAML:
XAML:
<Window x:Class="wpf_behaviour.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataGridDetailsSample" Height="200" Width="400">
<Grid Margin="10">
<DataGrid Name="dgUsers" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding Id}"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn Header="Age" Binding="{Binding Age}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Style.Triggers>
<DataTrigger Binding="{Binding Age}" Value="-1">
<Setter Property="IsEnabled" Value="False"/>
<Setter Property="ToolTip" Value="This filed is diabled."/>
<Setter Property="Background" Value="LightGray"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Correspoinding cs:
给出相应cs:
using System.Collections.Generic;
using System.Windows;
using System.Windows.Documents;
namespace wpf_behaviour
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<User> users = new List<User>();
users.Add(new User() { Id = 1, Name = "Kumar", Age = 10 });
users.Add(new User() { Id = 2, Name = "Sameer", Age = -1 });
users.Add(new User() { Id = 3, Name = "Danny", Age= 16 });
dgUsers.ItemsSource = users;
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
}
2 个解决方案
#1
0
I'm not sure why this happaning but you can catch the Enter Event and cancel the Edit:
我不知道为什么会发生这种情况,但是您可以捕获Enter事件并取消编辑:
C#
c#
private void MyDataGrid_OnKeyDown(object sender, KeyEventArgs e)
{
var dg = sender as DataGrid;
// alter this condition for whatever valid keys you want - avoid arrows/tab, etc.
if (dg != null && !dg.IsReadOnly && e.Key == Key.Enter)
{
dg.CancelEdit();
e.Handled = true;
}
}
XAML
XAML
<DataGrid Grid.Column="1" Name="dgUsers" AutoGenerateColumns="False" PreviewKeyDown="MyDataGrid_OnKeyDown">
#2
0
I got the solution (added a PreviewKeyDown event handler) and here it is and I would like to know any better solution as well:
我得到了解决方案(添加了PreviewKeyDown事件处理程序),在这里,我也想知道更好的解决方案:
private void DataGridCell_PreviewKeyDown(object sender, KeyEventArgs e)
{
try
{
DataGridCell cl = (DataGridCell)sender;
//Get the Cell's parent row
//using System.Windows.Media; for VisaualTreeHelper
var DataGridRowParent = VisualTreeHelper.GetParent(cl);
while (DataGridRowParent != null && DataGridRowParent.GetType() != typeof(DataGridRow))
{
DataGridRowParent = VisualTreeHelper.GetParent(DataGridRowParent);
}
//Get the Row's parent DataGrid
var DataGridParent = VisualTreeHelper.GetParent(DataGridRowParent);
while (DataGridParent != null && DataGridParent.GetType() != typeof(DataGrid))
{
DataGridParent = VisualTreeHelper.GetParent(DataGridParent);
}
DataGrid dp = DataGridParent as DataGrid;
//Get the CurrentCell value of DataGrid
DataGridCellInfo cli = dp.CurrentCell;
var CellContent = cli.Column.GetCellContent(cli.Item);
if (CellContent != null)
{
//Get DataGridCell of DataGridCellInfo
DataGridCell dgc = (DataGridCell)CellContent.Parent;
if (dgc.IsEnabled == false)
{
//If the key pressed is Enter or Tab allow
if (e.Key == Key.Enter || e.Key == Key.Tab)
{
e.Handled = false;
return;
}
//If any other key is pressed don't allow.
e.Handled = true;
return;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
#1
0
I'm not sure why this happaning but you can catch the Enter Event and cancel the Edit:
我不知道为什么会发生这种情况,但是您可以捕获Enter事件并取消编辑:
C#
c#
private void MyDataGrid_OnKeyDown(object sender, KeyEventArgs e)
{
var dg = sender as DataGrid;
// alter this condition for whatever valid keys you want - avoid arrows/tab, etc.
if (dg != null && !dg.IsReadOnly && e.Key == Key.Enter)
{
dg.CancelEdit();
e.Handled = true;
}
}
XAML
XAML
<DataGrid Grid.Column="1" Name="dgUsers" AutoGenerateColumns="False" PreviewKeyDown="MyDataGrid_OnKeyDown">
#2
0
I got the solution (added a PreviewKeyDown event handler) and here it is and I would like to know any better solution as well:
我得到了解决方案(添加了PreviewKeyDown事件处理程序),在这里,我也想知道更好的解决方案:
private void DataGridCell_PreviewKeyDown(object sender, KeyEventArgs e)
{
try
{
DataGridCell cl = (DataGridCell)sender;
//Get the Cell's parent row
//using System.Windows.Media; for VisaualTreeHelper
var DataGridRowParent = VisualTreeHelper.GetParent(cl);
while (DataGridRowParent != null && DataGridRowParent.GetType() != typeof(DataGridRow))
{
DataGridRowParent = VisualTreeHelper.GetParent(DataGridRowParent);
}
//Get the Row's parent DataGrid
var DataGridParent = VisualTreeHelper.GetParent(DataGridRowParent);
while (DataGridParent != null && DataGridParent.GetType() != typeof(DataGrid))
{
DataGridParent = VisualTreeHelper.GetParent(DataGridParent);
}
DataGrid dp = DataGridParent as DataGrid;
//Get the CurrentCell value of DataGrid
DataGridCellInfo cli = dp.CurrentCell;
var CellContent = cli.Column.GetCellContent(cli.Item);
if (CellContent != null)
{
//Get DataGridCell of DataGridCellInfo
DataGridCell dgc = (DataGridCell)CellContent.Parent;
if (dgc.IsEnabled == false)
{
//If the key pressed is Enter or Tab allow
if (e.Key == Key.Enter || e.Key == Key.Tab)
{
e.Handled = false;
return;
}
//If any other key is pressed don't allow.
e.Handled = true;
return;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}