IEditableObject的DataGrid验证行为

时间:2012-02-23 02:49:14

标签: wpf validation data-binding datagrid

用户点击DataGrid中的最后一行以添加新项时,我想要的行为

  1. 显示新行的项目编号;即,如果列表中有N个项目,则项目编号为n + 1。
  2. 将光标放在"名称"列,以便用户可以为该项目命名。
  3. 如果用户未输入名称,请指出错误
    • 在该行显示一个错误字形。
    • Hilight the Name DataGridCell。
    • 显示消息"名称是必需的"作为工具提示。
  4. 如果我单独使用IDataErrorInfo,我会收到一些接近但不正确的信息:新的订单项已经处于错误状态,而没有让用户有机会输入任何内容!

    enter image description here

    所以我尝试添加IEditableObject并使用布尔值IsItemNew标志。但是使用下面的代码错误根本不会显示出来。

    如何修复我的代码以获得我想要的行为?

    干杯,
    Berryl

    enter image description here

    GroceryItem代码

    #region Implementation of IDataErrorInfo
    
    public string this[string columnName] {
        get {
            if(IsNewItem) return string.Empty;
    
            if (columnName == "Name") {
                if (string.IsNullOrEmpty(Name))
                    return "The name of the item to buy is required";
            }
    
            return string.Empty;
        }
    }
    
    public string Error
    {
        get
        {
            var error = new StringBuilder();
    
            // iterate over all of the properties
            // of this object - aggregating any validation errors
            var props = TypeDescriptor.GetProperties(this);
            foreach (PropertyDescriptor prop in props)
            {
                var propertyError = this[prop.Name];
                if (propertyError != string.Empty) {
                    var leadingString = (error.Length != 0 ? ", " : "");
                    error.Append(leadingString + propertyError);
                }
            }
    
            return error.Length == 0 ? null : error.ToString();
        }
    }
    
    private void NotifyErrorChanged() { RaisePropertyChangedEvent("Error"); }
    
    #endregion
    
    #region Implementation of IEditableObject
    
    public bool IsNewItem { get; private set; }
    
    public void BeginEdit() {
        IsNewItem = true;
    }
    
    public void EndEdit() {
        IsNewItem = false;
        if(Error!=null) 
            NotifyErrorChanged();
    }
    
    public void CancelEdit() { IsNewItem = false; }
    
    #endregion
    

    MainViewModel代码

    public ObservableCollection<GroceryItem> GroceryList
    {
        get { return _groceryList; }
    
        set
        {
            _groceryList = value;
            RaisePropertyChangedEvent("GroceryList");
        }
    }
    private ObservableCollection<GroceryItem> _groceryList;
    
    void OnGroceryListChanged(object sender, NotifyCollectionChangedEventArgs e) {
    
        ...
    
        // Resequence the list
        SequencingService.SetCollectionSequence(GroceryList);
    
    }
    

    DataGrid xaml

        

        <Style x:Key="RowStyle" TargetType="{x:Type DataGridRow}">
            <Setter Property="AllowDrop" Value="True" />
            <Setter Property="ValidationErrorTemplate">
                <Setter.Value>
                    <ControlTemplate>
                        <Grid>
                            <Ellipse Width="12" Height="12"
                        Fill="Red" Stroke="Black"
                        StrokeThickness="0.5"/>
                            <TextBlock FontWeight="Bold" Padding="4,0,0,0"
                        Margin="0" VerticalAlignment="Top" Foreground="White" Text="!"
                        ToolTip="{Binding RelativeSource={RelativeSource
                                 FindAncestor, AncestorType={x:Type DataGridRow}},
                                 Path=(Validation.Errors)[0].ErrorContent}"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
    </Window.Resources>
    
    <DockPanel>
    
        <DataGrid 
            x:Name="MainGrid" RowStyle="{StaticResource RowStyle}" CanUserAddRows="True"
            ItemsSource="{Binding GroceryList}" SelectedItem="{Binding SelectedItem}" 
            AutoGenerateColumns="False" 
                ...
            >
    
            <DataGrid.Columns>
                <DataGridTextColumn Header="" Width="40" ElementStyle="{StaticResource NumberStyle}" Binding="{Binding SequenceNumber, Mode=OneWay}" IsReadOnly="True" />
                <DataGridTextColumn Header="Item" Width="*" Binding="{Binding Name, ValidatesOnDataErrors=True}" IsReadOnly="False" />
            </DataGrid.Columns>
        </DataGrid>
    
    </DockPanel>
    

1 个答案:

答案 0 :(得分:0)

我结束了新条目名称的插入值,如下所示。现在IEditableObject所要做的就是删除Cancel上的项目。

干杯,
Berryl

    #region Implementation of IEditableObject

    public void BeginEdit() { }

    public void EndEdit() { }

    public void CancelEdit() {
        Debug.Assert(GroceryList!=null);
        GroceryList.Remove(this);
    }

    #endregion

enter image description here