【发布时间】:2020-02-10 00:31:32
【问题描述】:
在 WPF DataGrid 中,我想在单元格内的一个小框中显示验证结果。
我通过绑定到Validation.Errors 数据结构(请参见下面的代码)设法为单个列做到这一点。
这就是我得到的,它非常接近预期的结果;现在我想为所有列实现它。
问题
为了使解决方案可在多个列上重复使用,我尝试将其移动到 ControlTemplate 中。我找不到从控件模板内部再次建立Validation.Errors 绑定的方法(请参见下面的代码)。结果,红色标签始终为空。
有效的单列解决方案
工作解决方案基于以下代码:
<DataGrid ItemsSource="{Binding People}" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Label x:Name="x" Content="{Binding Name}"/>
<Label Padding="2" HorizontalAlignment="Right" VerticalAlignment="Top" Height="15" Width="44" FontSize="8" Foreground="White" Background="Red"
Content="{Binding ElementName='x', Path='(Validation.Errors)[0].ErrorContent'}"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
无需全部阅读:这里是相关部分
它通过将标签“x”绑定到我的示例数据上下文的名称属性来工作。
<Label x:Name="x" Content="{Binding Name}"/>
然后,错误标签依次绑定到前一个标签(通过其名称)并获取Validation.Errors 信息(为了清楚起见,此处删除了图形格式)。
<Label Content="{Binding ElementName='x', Path='(Validation.Errors)[0].ErrorContent'}"/>
这证明结果是可以实现的,但是这个方案不能在多列上重复使用,而不是一遍遍地重复。
包装尝试
为了有一个可重复使用的模板,我尝试将我所有的单元格控件(标签 x 和带有 x 错误的标签)包装到 ControlTemplate 中;它将被一个标签组件使用,这是我在网格上实际拥有的。
包装代码是这样的(下面是完整的代码):
<Label Content="{Binding Name}">
<Label.Template>
<ControlTemplate TargetType="Label">
//my controls
</ControlTemplate>
</Label.Template>
</Label>
关于“我的控制”
我不得不换行:
<Label x:Name="x" Content="{Binding Name}"/>
到这里:
<Label x:Name="x" Content="{TemplateBinding Content}"/>
但专用于错误的标签不再起作用(图形配置已删除):
我可以猜测它不起作用,因为只有 content 属性从模板标签转移到内部标签 x;内容而不是属性的整个“状态”,包括验证错误集合。 但是我怎样才能访问这些错误?
代码
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<DataGrid ItemsSource="{Binding People}" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Name}">
<Label.Template>
<ControlTemplate TargetType="Label">
<Grid>
<Label x:Name="x" Content="{TemplateBinding Content}"/>
<Label Padding="2" HorizontalAlignment="Right" VerticalAlignment="Top" Height="15" Width="44" FontSize="8" Foreground="White" Background="Red"
Content="{Binding ElementName='x', Path='(Validation.Errors)[0].ErrorContent'}"/>
</Grid>
</ControlTemplate>
</Label.Template>
</Label>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
数据上下文
public class ViewModel
{
public ObservableCollection<Person> People { get; } = new ObservableCollection<Person>() { new Person { Name = "Alan" } };
}
public class Person: INotifyDataErrorInfo
{
public string Name { get; set; }
public bool HasErrors => true;
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public IEnumerable GetErrors(string propertyName)
{
yield return "Some error";
}
}
【问题讨论】:
标签: c# wpf datagrid controltemplate