В WPF DataGrid я хочу показать результат проверки в небольшом поле внутри ячейки.
Мне удалось сделать это для одного столбца, связавшись со структурой данных Validation.Errors
(см. Код ниже) .
Это то, что я получил, и это довольно близко к желаемому результату; Теперь я хочу реализовать это для всех столбцов.
Проблема
Чтобы сделать решение многократно используемым по нескольким столбцам, я попытался переместить его в ControlTemplate. Я не смог найти способ установить sh привязку 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" к свойству Name моего примера datacontext.
<Label x:Name="x" Content="{Binding Name}"/>
Затем метка ошибки в свою очередь связывается с предыдущей меткой (через свое имя) и получает информацию Validation.Errors
(графические форматы здесь удалены для ясности).
<Label Content="{Binding ElementName='x', Path='(Validation.Errors)[0].ErrorContent'}"/>
Это доказывает, что результат достижим, но это решение нельзя использовать повторно для нескольких столбцов, не повторяя его снова и снова.
Попытка обтекания
Чтобы получить шаблон многократного использования, я попытался обернуть все мои контуры ячеек (метка x и метка с ошибками x) в ControlTemplate; он будет использоваться компонентом Label, который фактически будет у меня в сетке.
Код переноса таков (ниже приведен полный код):
<Label Content="{Binding Name}">
<Label.Template>
<ControlTemplate TargetType="Label">
//my controls
</ControlTemplate>
</Label.Template>
</Label>
About "мои элементы управления "
Мне пришлось изменить строку:
<Label x:Name="x" Content="{Binding Name}"/>
на эту:
<Label x:Name="x" Content="{TemplateBinding Content}"/>
Но ярлык, посвященный ошибкам, больше не работает (конфигурация графики удалена) :
Я могу догадаться, что это не работает, потому что только свойство содержимого передается из шаблонной метки в внутренняя метка х; содержание, а не все «состояние» свойства, включая коллекцию ошибок проверки. Но как я могу получить доступ к этим ошибкам тогда ?
Код
<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>
DataContext
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";
}
}