首页 > 解决方案 > 为什么 ObservableCollection 中的验证红色框出现在容器的左上角?

问题描述

我在文本框中遇到验证问题,我将尝试以简单的方式重现。我正在使用本身包含 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>

印刷丝网

标签: c#wpfxaml

解决方案


我仍然不知道是什么导致了这个问题,但至少我找到了一个在 TextBox 中使用 AdornerDecorator 并定义它们的边距的解决方案:

<UserControl ...>
    <StackPanel Orientation="Horizontal">
        <AdornerDecorator Margin="4">
            <TextBox Width="70" Margin="1" Text="{Binding Value1, ValidatesOnDataErrors=True,
            UpdateSourceTrigger=PropertyChanged}"/>
        </AdornerDecorator>
        <AdornerDecorator Margin="4">
            <TextBox Width="70" Margin="1" Text="{Binding Value2, ValidatesOnDataErrors=True,
            UpdateSourceTrigger=PropertyChanged}"/>
        </AdornerDecorator>
    </StackPanel>
</UserControl>

推荐阅读