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 是我的模型,具有四个不同的属性:MoveCtrlSpeedLimitMode 和最后一个不可见的 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。从那里,我可以找到行索引。