ValidationRule:在数据网格 WPF C# 中获取选定的组合框行号
ValidationRule : Get selected combobox row number within datagrid WPF C#
我创建了一个数据网格,其中每一行代表我们实验室中一台机器的命令。我想通过在我的代码中实施验证规则来限制用户对“限制模式”列中 select“相对”的选择。仅当与此行关联的移动控件与前一行相同时,用户才能使用“相对”限制模式(见图)。否则应该有一条消息警告他。
我设法创建了一个有效的 RowValidationRules:
XAML:
<DataGrid.RowValidationRules>
<utility:RelativeLimitModeRule ValidationStep="UpdatedValue"/>
</DataGrid.RowValidationRules>
验证规则:
class RelativeLimitModeRule : ValidationRule
{
//Makes sure that if "Relative" move position is selected, the previous command had the same MoveCtrl (otherwise relative is bullshit)
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if (value is BindingGroup bg && bg.Items.Count > 0)
{
if ((bg.Items[0] as DoliInput).LimMode == "Relative")
{
if (bg.Owner is DataGridRow dgrow)
{
DataGrid dg = GetParent<DataGrid>(dgrow);
int currItemKey = ((bg.Items[0]) as DoliInput).SequenceNumber - 1;
if (currItemKey > 0)
{
if (((((InteractiveGraph.MVVM.ViewModel)dg.DataContext).DoliInputCollection)[currItemKey - 1]).MoveCtrl != (bg.Items[0] as DoliInput).MoveCtrl)
{
return new ValidationResult(false, $"To use the \"Relative\" option, the previous command should have the same Move Ctrl as this one ");
}
}
}
}
}
return ValidationResult.ValidResult;
//return new ValidationResult(true, null);
}
private static T GetParent<T>(DependencyObject d) where T : class
{
while (d != null && !(d is T))
{
d = VisualTreeHelper.GetParent(d);
}
return d as T;
}
}
其中 DoliInput
是我的模型,具有四个不同的属性:MoveCtrl
、Speed
、LimitMode
和最后一个不可见的 SequenceNumber
跟踪命令的位置 DoliInputCollection
这是一个 ObservableCollection
即 stores/lists 机器要处理的所有命令。
但是,以这种方式实施时,验证规则仅在用户 select 另一行并修改“Spe”列时触发。
我修改了 XAML,因此只要用户 select 将“相对”设置为限制模式,验证规则就会触发:
新 Xaml:
<DataGridTemplateColumn Header="Limit Mode">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding LimModeItem}">
<ComboBox.SelectedItem>
<Binding Path="LimMode"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<utility:RelativeLimitModeRule>
</utility:RelativeLimitModeRule>
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedItem>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding LimModeItem}"
SelectedItem="{Binding LimMode, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
但是现在验证规则中的 value
参数 returns select 字符串,我无法访问行索引,我需要在当前行 Move Control 和上一行。
使用 Combobox_DropDownOpened 事件,我能够检索行索引。
private void ComboBox_DropDownOpened(object sender, EventArgs e)
{
var cb = ((System.Windows.Controls.ComboBox)sender);
DataGridRow dataGridRow = VisualHelper.FindParent<DataGridRow>(cb);
int index = dataGridRow.GetIndex();
}
但我想保持我的 CodeBehind 清晰。所以我尝试使用 Interactivity 将命令绑定到 DropDownEvent,但我不知道如何像使用事件那样处理发件人。
我走的路对吗?如果是这样,我该怎么做才能使用命令检索行号?是否有更好的设置验证规则?
好的,ValidationStep="UpdatedValue"
不仅定义了when the Validation rule is fired,而且对发送给validationrule的value
也有影响
从
<DataTemplate>
<ComboBox ItemsSource = "{Binding LimModeItem}" >
< ComboBox.SelectedItem >
< Binding Path="LimMode"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<utility:RelativeLimitModeRule/>
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedItem>
</ComboBox>
</DataTemplate>
到
<DataTemplate>
<ComboBox ItemsSource = "{Binding LimModeItem}" >
< ComboBox.SelectedItem >
< Binding Path="LimMode"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<utility:RelativeLimitModeRule ValidationStep="UpdatedValue"/ >
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedItem>
</ComboBox>
</DataTemplate>
value
参数的类型从 string
变为 BindingExpression
。从那里,我可以找到行索引。
我创建了一个数据网格,其中每一行代表我们实验室中一台机器的命令。我想通过在我的代码中实施验证规则来限制用户对“限制模式”列中 select“相对”的选择。仅当与此行关联的移动控件与前一行相同时,用户才能使用“相对”限制模式(见图)。否则应该有一条消息警告他。
我设法创建了一个有效的 RowValidationRules:
XAML:
<DataGrid.RowValidationRules>
<utility:RelativeLimitModeRule ValidationStep="UpdatedValue"/>
</DataGrid.RowValidationRules>
验证规则:
class RelativeLimitModeRule : ValidationRule
{
//Makes sure that if "Relative" move position is selected, the previous command had the same MoveCtrl (otherwise relative is bullshit)
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if (value is BindingGroup bg && bg.Items.Count > 0)
{
if ((bg.Items[0] as DoliInput).LimMode == "Relative")
{
if (bg.Owner is DataGridRow dgrow)
{
DataGrid dg = GetParent<DataGrid>(dgrow);
int currItemKey = ((bg.Items[0]) as DoliInput).SequenceNumber - 1;
if (currItemKey > 0)
{
if (((((InteractiveGraph.MVVM.ViewModel)dg.DataContext).DoliInputCollection)[currItemKey - 1]).MoveCtrl != (bg.Items[0] as DoliInput).MoveCtrl)
{
return new ValidationResult(false, $"To use the \"Relative\" option, the previous command should have the same Move Ctrl as this one ");
}
}
}
}
}
return ValidationResult.ValidResult;
//return new ValidationResult(true, null);
}
private static T GetParent<T>(DependencyObject d) where T : class
{
while (d != null && !(d is T))
{
d = VisualTreeHelper.GetParent(d);
}
return d as T;
}
}
其中 DoliInput
是我的模型,具有四个不同的属性:MoveCtrl
、Speed
、LimitMode
和最后一个不可见的 SequenceNumber
跟踪命令的位置 DoliInputCollection
这是一个 ObservableCollection
即 stores/lists 机器要处理的所有命令。
但是,以这种方式实施时,验证规则仅在用户 select 另一行并修改“Spe”列时触发。
我修改了 XAML,因此只要用户 select 将“相对”设置为限制模式,验证规则就会触发:
新 Xaml:
<DataGridTemplateColumn Header="Limit Mode">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding LimModeItem}">
<ComboBox.SelectedItem>
<Binding Path="LimMode"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<utility:RelativeLimitModeRule>
</utility:RelativeLimitModeRule>
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedItem>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding LimModeItem}"
SelectedItem="{Binding LimMode, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
但是现在验证规则中的 value
参数 returns select 字符串,我无法访问行索引,我需要在当前行 Move Control 和上一行。
使用 Combobox_DropDownOpened 事件,我能够检索行索引。
private void ComboBox_DropDownOpened(object sender, EventArgs e)
{
var cb = ((System.Windows.Controls.ComboBox)sender);
DataGridRow dataGridRow = VisualHelper.FindParent<DataGridRow>(cb);
int index = dataGridRow.GetIndex();
}
但我想保持我的 CodeBehind 清晰。所以我尝试使用 Interactivity 将命令绑定到 DropDownEvent,但我不知道如何像使用事件那样处理发件人。
我走的路对吗?如果是这样,我该怎么做才能使用命令检索行号?是否有更好的设置验证规则?
好的,ValidationStep="UpdatedValue"
不仅定义了when the Validation rule is fired,而且对发送给validationrule的value
也有影响
从
<DataTemplate>
<ComboBox ItemsSource = "{Binding LimModeItem}" >
< ComboBox.SelectedItem >
< Binding Path="LimMode"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<utility:RelativeLimitModeRule/>
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedItem>
</ComboBox>
</DataTemplate>
到
<DataTemplate>
<ComboBox ItemsSource = "{Binding LimModeItem}" >
< ComboBox.SelectedItem >
< Binding Path="LimMode"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<utility:RelativeLimitModeRule ValidationStep="UpdatedValue"/ >
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedItem>
</ComboBox>
</DataTemplate>
value
参数的类型从 string
变为 BindingExpression
。从那里,我可以找到行索引。