如何对 WPF Datagrid 单元格中输入的每个值执行事件
How to Execute Event on Each Value Entered in WPF Datagrid Cell
每次我写任何一个字时,我都试图执行一个事件。例如,当我在一个单元格中写“123”时,我想 运行 一个事件三次,每次输入一个值。
我使用 "TargetUpdated" 事件并写入 1,事件 运行 成功,但是当我再次写入 2 和 3 时,事件没有 运行。请在下面查看我的代码:
private void maingrid_TargetUpdated(object sender, DataTransferEventArgs e)
{
try
{
DataGrid Currcell = sender as DataGrid;
int index = Currcell.CurrentColumn.DisplayIndex;
vm.SetLineTotals(vm.Tax, vm.DiscountPer);
}
catch
{
}
}
实现此行为的原因是获取每个输入值的 datagrid linetotal 总和。请任何人帮助和指导,谢谢。
更新:
请从下方 link 获取我正在尝试解释的视频。
Sample Video
尝试使用 KeyDown 事件而不是 TargetUpdated。每次你按下一个键它都会调用这个事件。
更多关键行为:
据我所知,您需要某种机制来处理数据网格单元格上的用户键盘输入。在这里我可以建议你;使用两个附加属性。第一个是启用处理机制的布尔值,第二个是一个 Action,它将支持视图模型的操作来执行处理本身。您可以通过 DataGridCell 的样式附加此功能。这是一个描述的解决方案:
1. Xaml:
<Window x:Class="soHelpProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:soHelpProject="clr-namespace:SoHelpProject"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<soHelpProject:MainViewModel/>
</Window.DataContext>
<Grid>
<DataGrid ItemsSource="{Binding Collection}" AutoGenerateColumns="False">
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<Setter Property="soHelpProject:Attached.IsReactsOnKeyDown" Value="True"></Setter>
<Setter Property="soHelpProject:Attached.OnKeyDownAction" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.OnKeyDownAction}"></Setter>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Width="120" Binding="{Binding Name}"></DataGridTextColumn>
<DataGridTextColumn Width="120" Binding="{Binding Surname}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid></Window>
2。附加属性代码:
public class Attached
{
public static readonly DependencyProperty OnKeyDownActionProperty = DependencyProperty.RegisterAttached(
"OnKeyDownAction", typeof (Action<object>), typeof (Attached), new PropertyMetadata(default(Action<object>)));
public static void SetOnKeyDownAction(DependencyObject element, Action<object> value)
{
element.SetValue(OnKeyDownActionProperty, value);
}
public static Action<object> GetOnKeyDownAction(DependencyObject element)
{
return (Action<object>) element.GetValue(OnKeyDownActionProperty);
}
public static readonly DependencyProperty IsReactsOnKeyDownProperty = DependencyProperty.RegisterAttached(
"IsReactsOnKeyDown", typeof (bool), typeof (Attached), new PropertyMetadata(default(bool), IsReactsOnKeyDownPropertyChangedCallback));
private static void IsReactsOnKeyDownPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
var val = (bool)args.NewValue;
var cell = sender as DataGridCell;
if(cell == null)
return;
if (val == false)
{
cell.KeyDown -= CellOnKeyDown;
}
else
{
cell.KeyDown += CellOnKeyDown;
}
}
private static void CellOnKeyDown(object sender, KeyEventArgs keyEventArgs)
{
var cell = sender as DataGridCell;
if (cell == null)
return;
var action = cell.GetValue(OnKeyDownActionProperty) as Action<object>;
if (action == null) return;
action(keyEventArgs);
}
public static void SetIsReactsOnKeyDown(DependencyObject element, bool value)
{
element.SetValue(IsReactsOnKeyDownProperty, value);
}
public static bool GetIsReactsOnKeyDown(DependencyObject element)
{
return (bool) element.GetValue(IsReactsOnKeyDownProperty);
}
}
3。 ViewModel 和模型代码:
public class MainViewModel:BaseObservableObject
{
private Action<object> _onKeyDownAction;
private ObservableCollection<Person> _collection;
public MainViewModel()
{
Collection = new ObservableCollection<Person>
{
new Person
{
Name = "John",
Surname = "A"
},
new Person
{
Name = "John",
Surname = "B"
},
new Person
{
Name = "John",
Surname = "C"
},
};
OnKeyDownAction = new Action<object>(KeyWasPressed);
}
private void KeyWasPressed(object o)
{
var args = o as KeyEventArgs;
if(args == null)
return;
Debug.WriteLine(args.Key.ToString());
}
public Action<object> OnKeyDownAction
{
get { return _onKeyDownAction; }
set
{
_onKeyDownAction = value;
OnPropertyChanged();
}
}
public ObservableCollection<Person> Collection
{
get { return _collection; }
set
{
_collection = value;
OnPropertyChanged();
}
}
}
public class Person:BaseObservableObject
{
private string _name;
private string _surname;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged();
}
}
public string Surname
{
get { return _surname; }
set
{
_surname = value;
OnPropertyChanged();
}
}
}
- 首先试着冷静下来,干得好,申请看起来不错,所以是xaml。
- 据我所见ALL你的更新逻辑是基于PreviewKeyDown的,在'preview'的那一刻仍然有旧值。当值已更改时,请尝试将您的逻辑基于 PreviewKeyUp 或基于 KeyUp。让我知道它是否有帮助。
希望对您有所帮助。
此致,
每次我写任何一个字时,我都试图执行一个事件。例如,当我在一个单元格中写“123”时,我想 运行 一个事件三次,每次输入一个值。
我使用 "TargetUpdated" 事件并写入 1,事件 运行 成功,但是当我再次写入 2 和 3 时,事件没有 运行。请在下面查看我的代码:
private void maingrid_TargetUpdated(object sender, DataTransferEventArgs e)
{
try
{
DataGrid Currcell = sender as DataGrid;
int index = Currcell.CurrentColumn.DisplayIndex;
vm.SetLineTotals(vm.Tax, vm.DiscountPer);
}
catch
{
}
}
实现此行为的原因是获取每个输入值的 datagrid linetotal 总和。请任何人帮助和指导,谢谢。
更新: 请从下方 link 获取我正在尝试解释的视频。 Sample Video
尝试使用 KeyDown 事件而不是 TargetUpdated。每次你按下一个键它都会调用这个事件。
更多关键行为:
据我所知,您需要某种机制来处理数据网格单元格上的用户键盘输入。在这里我可以建议你;使用两个附加属性。第一个是启用处理机制的布尔值,第二个是一个 Action,它将支持视图模型的操作来执行处理本身。您可以通过 DataGridCell 的样式附加此功能。这是一个描述的解决方案: 1. Xaml:
<Window x:Class="soHelpProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:soHelpProject="clr-namespace:SoHelpProject"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<soHelpProject:MainViewModel/>
</Window.DataContext>
<Grid>
<DataGrid ItemsSource="{Binding Collection}" AutoGenerateColumns="False">
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<Setter Property="soHelpProject:Attached.IsReactsOnKeyDown" Value="True"></Setter>
<Setter Property="soHelpProject:Attached.OnKeyDownAction" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.OnKeyDownAction}"></Setter>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Width="120" Binding="{Binding Name}"></DataGridTextColumn>
<DataGridTextColumn Width="120" Binding="{Binding Surname}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid></Window>
2。附加属性代码:
public class Attached
{
public static readonly DependencyProperty OnKeyDownActionProperty = DependencyProperty.RegisterAttached(
"OnKeyDownAction", typeof (Action<object>), typeof (Attached), new PropertyMetadata(default(Action<object>)));
public static void SetOnKeyDownAction(DependencyObject element, Action<object> value)
{
element.SetValue(OnKeyDownActionProperty, value);
}
public static Action<object> GetOnKeyDownAction(DependencyObject element)
{
return (Action<object>) element.GetValue(OnKeyDownActionProperty);
}
public static readonly DependencyProperty IsReactsOnKeyDownProperty = DependencyProperty.RegisterAttached(
"IsReactsOnKeyDown", typeof (bool), typeof (Attached), new PropertyMetadata(default(bool), IsReactsOnKeyDownPropertyChangedCallback));
private static void IsReactsOnKeyDownPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
var val = (bool)args.NewValue;
var cell = sender as DataGridCell;
if(cell == null)
return;
if (val == false)
{
cell.KeyDown -= CellOnKeyDown;
}
else
{
cell.KeyDown += CellOnKeyDown;
}
}
private static void CellOnKeyDown(object sender, KeyEventArgs keyEventArgs)
{
var cell = sender as DataGridCell;
if (cell == null)
return;
var action = cell.GetValue(OnKeyDownActionProperty) as Action<object>;
if (action == null) return;
action(keyEventArgs);
}
public static void SetIsReactsOnKeyDown(DependencyObject element, bool value)
{
element.SetValue(IsReactsOnKeyDownProperty, value);
}
public static bool GetIsReactsOnKeyDown(DependencyObject element)
{
return (bool) element.GetValue(IsReactsOnKeyDownProperty);
}
}
3。 ViewModel 和模型代码:
public class MainViewModel:BaseObservableObject
{
private Action<object> _onKeyDownAction;
private ObservableCollection<Person> _collection;
public MainViewModel()
{
Collection = new ObservableCollection<Person>
{
new Person
{
Name = "John",
Surname = "A"
},
new Person
{
Name = "John",
Surname = "B"
},
new Person
{
Name = "John",
Surname = "C"
},
};
OnKeyDownAction = new Action<object>(KeyWasPressed);
}
private void KeyWasPressed(object o)
{
var args = o as KeyEventArgs;
if(args == null)
return;
Debug.WriteLine(args.Key.ToString());
}
public Action<object> OnKeyDownAction
{
get { return _onKeyDownAction; }
set
{
_onKeyDownAction = value;
OnPropertyChanged();
}
}
public ObservableCollection<Person> Collection
{
get { return _collection; }
set
{
_collection = value;
OnPropertyChanged();
}
}
}
public class Person:BaseObservableObject
{
private string _name;
private string _surname;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged();
}
}
public string Surname
{
get { return _surname; }
set
{
_surname = value;
OnPropertyChanged();
}
}
}
- 首先试着冷静下来,干得好,申请看起来不错,所以是xaml。
- 据我所见ALL你的更新逻辑是基于PreviewKeyDown的,在'preview'的那一刻仍然有旧值。当值已更改时,请尝试将您的逻辑基于 PreviewKeyUp 或基于 KeyUp。让我知道它是否有帮助。
希望对您有所帮助。 此致,