【问题标题】:DataGrid Validation Behavior with IEditableObject使用 IEditableObject 的 DataGrid 验证行为
【发布时间】:2012-02-23 02:49:14
【问题描述】:

这是当用户单击 DataGrid 中的最后一行以添加新项目时我想要的行为

  1. 显示新行的项号;即,如果列表中有 N 个项目,则项目编号为 n + 1。
  2. 将光标置于“名称”列,以便用户为项目命名。
  3. 如果用户未输入名称,则通过以下方式指示错误
    • 在行中显示错误字形。
    • 突出显示名称 DataGridCell。
    • 将消息“需要名称”显示为工具提示。

如果我单独使用 IDataErrorInfo,我会得到一些接近但不正确的结果:新行项目已经出现错误,而没有给用户输入任何内容的机会!

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

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

干杯,
浆果

杂货商品代码

#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>

【问题讨论】:

    标签: wpf validation data-binding datagrid


    【解决方案1】:

    我最终为新条目的名称设置了一个插入值,如下所示。现在 IEditableObject 所要做的就是在 Cancel 上删除该项目。

    干杯,
    浆果

        #region Implementation of IEditableObject
    
        public void BeginEdit() { }
    
        public void EndEdit() { }
    
        public void CancelEdit() {
            Debug.Assert(GroceryList!=null);
            GroceryList.Remove(this);
        }
    
        #endregion
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-25
      • 2012-12-09
      • 2018-09-06
      • 2011-09-29
      • 1970-01-01
      • 1970-01-01
      • 2011-04-21
      • 2017-08-10
      相关资源
      最近更新 更多