Поведение валидации DataGrid с IEditableObject - PullRequest
1 голос
/ 23 февраля 2012

Вот поведение, которое я хочу, когда пользователь нажимает на последнюю строку в DataGrid, чтобы добавить новый элемент :

  1. Показать номер позиции новой строки; то есть, если в списке есть N элементов, номер элемента будет n + 1.
  2. Поместите курсор в столбец «Имя», чтобы пользователь мог присвоить элементу имя.
  3. Если пользователь не вводит имя, укажите ошибку
    • Отображение символа ошибки в строке.
    • Подсветка имени DataGridCell.
    • Показать сообщение «Имя обязательно» в качестве всплывающей подсказки.

Если я использую только IDataErrorInfo, я получаю что-то близкое, но не правильное: новая позиция уже находится в состоянии Ошибка, не предоставив пользователю возможности что-либо ввести!

enter image description here

Поэтому я попытался добавить в IEditableObject и использовать логический флаг IsItemNew. Но при использовании приведенного ниже кода ошибка не появляется вообще.

Как я могу исправить свой код, чтобы получить поведение, которое я хочу?

Приветствия
Berryl

enter image description here

Код товара

#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 голосов
/ 25 февраля 2012

Я установил засоренное значение для имени новой записи, как показано ниже.Теперь все, что IEditableObject должен сделать, это удалить элемент на отмену.

...