У меня проблема с проверкой в текстовых полях, которую я постараюсь воспроизвести простым способом. Я использую ObservableColletion объектов, которые сами содержат ObservableColletion. В моих UserControls я привязываюсь к свойствам моих объектов, в которых я использую валидацию (в этом примере IDataErrorInfo). Проблема в том, что когда я запускаю программу с уже вставленными данными. Если в данных мало ошибок, красные поля проверки появляются в правильном месте (текстовые поля, в которых есть ошибки), но если у меня больше определенного количества ошибок, красные поля начинают появляться в верхнем левом углу контейнера списка , Может кто-нибудь объяснить мне, что происходит и как я могу решить эту проблему?
Вот код:
<Window ...>
<Window.Resources>
<DataTemplate DataType="{x:Type local:Group}">
<local:UserControlGroup/>
</DataTemplate>
</Window.Resources>
<GroupBox Header="Group List">
<ListBox BorderThickness="0" ItemsSource="{Binding Groups}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="4"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</GroupBox>
</window>
В частичном классе я создаю 7 похожих объектов:
public partial class MainWindow : Window
{
public ObservableCollection<Group> Groups { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
Groups = new ObservableCollection<Group>()
{
new Group()
{
Name = "Group01",
Type = "AAAA",
ItemList = new ObservableCollection<Item>()
{
new Item()
{
Value1 = -2,
Value2 = -1
},
new Item()
{
Value1 = -2,
Value2 = -1
},
new Item()
{
Value1 = -2,
Value2 = -1
},
new Item()
{
Value1 = -2,
Value2 = -1
},
new Item()
{
Value1 = -2,
Value2 = -1
},
new Item()
{
Value1 = -2,
Value2 = -1
}
}
},
new Group()
{
Name = "Group02",
Type = "BBBB",
ItemList = new ObservableCollection<Item>()
{
new Item()
{
Value1 = -2,
...
...
new Group()
{
Name = "Group07",
Type = "BBBB",
ItemList = new ObservableCollection<Item>()
{
...
Классы и пользовательские элементы управления:
public class Group : IDataErrorInfo
{
public string Name { get; set; }
public string Type { get; set; }
public ObservableCollection<Item> ItemList { get; set; }
public string Error => throw new NotImplementedException();
public string this[string columnName]
{
get
{
if (columnName == nameof(Name))
{
if (string.IsNullOrEmpty(Name)) return "Value can't be empty.";
}
return string.Empty;
}
}
}
<UserControl ...>
<UserControl.Resources>
<DataTemplate DataType="{x:Type local:Item}">
<local:UserControlItem/>
</DataTemplate>
</UserControl.Resources>
<GroupBox Header="{Binding Name}">
<StackPanel>
<TextBox HorizontalAlignment="Left" Width="70" Margin="4" Text="{Binding Type, ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}"/>
<ItemsControl ItemsSource="{Binding ItemList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</GroupBox>
</UserControl>
public class Item : IDataErrorInfo
{
public int Value1 { get; set; }
public int Value2 { get; set; }
public string Error => throw new NotImplementedException();
public string this[string columnName]
{
get
{
if (columnName == nameof(Value1))
{
if (Value1 < 0) return "Value can't be negative.";
}
else if (columnName == nameof(Value2))
{
if (Value1 < 0) return "Value can't be negative.";
}
return string.Empty;
}
}
}
<UserControl ...>
<StackPanel Orientation="Horizontal">
<TextBox Width="70" Margin="4" Text="{Binding Value1, ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Width="70" Margin="4" Text="{Binding Value2, ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</UserControl>
Экран печати