【发布时间】:2012-02-23 02:49:14
【问题描述】:
这是当用户单击 DataGrid 中的最后一行以添加新项目时我想要的行为:
- 显示新行的项号;即,如果列表中有 N 个项目,则项目编号为 n + 1。
- 将光标置于“名称”列,以便用户为项目命名。
- 如果用户未输入名称,则通过以下方式指示错误
- 在行中显示错误字形。
- 突出显示名称 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