首页 > 解决方案 > ValidationRule:在datagrid WPF C#中获取选定的组合框行号

问题描述

我创建了一个数据网格,其中每一行代表我们实验室中一台机器的命令。我想通过在我的代码中实现验证规则来限制用户在“限制模式”列中选择“相对”的选项。仅当与此行关联的移动控件和前一行相同时,用户才能使用“相对”限制模式(见图)。否则一条消息应该警告他。

验证规则原则

我设法创建了一个有效的 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,它跟踪命令的位置,其中存储/列出要由机器处理的所有命令。但是,以这种方式实现时,验证规则仅在用户选择另一行并修改“Spe”列时触发。LimitModeSequenceNumberDoliInputCollectionObservableCollection

我修改了 XAML,因此只要用户选择“相对”作为限制模式,验证规则就会触发:

新的 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验证规则中的参数返回选择字符串,并且我无法访问在当前行移动控件和前一个行之间进行比较所需的行索引。

使用 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,但我不知道如何像使用事件那样处理发送方。

我走对了吗?如果是这样,我该如何使用命令检索行号?有没有更好的设置验证规则?

标签: c#wpfcomboboxdatagrid

解决方案


好吧,ValidationStep="UpdatedValue"不仅定义了何时触发验证规则,而且它还对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>

参数的类型valuestring变为BindingExpression。从那里,我可以找到行索引。


推荐阅读