列表框没有显示我的第一个项目

时间:2011-04-17 15:56:49

标签: c# wpf mvvm

我在使用WPF时遇到了一个小问题,并将我的listbox / listview绑定到自定义列表。

此列表包含IEnumerator& IEnumerable接口已实现。如果我将控件绑定到那些,我永远不会看到该列表的第一个对象。

当我是gridview时,它确实显示了我的第一个对象。因此,由于某种原因,listbox / listview正在执行不同的操作来枚举我的自定义列表。

我的绑定用于两种设置完全相同的方式,使用我的ViewModel上的公共属性。

Binding(我的PersonObject有一个公共属性ProjectList,它获取我正在谈论的自定义列表)。

 public Person Person
    {
        get
        {
            return this._person;
        }
        set
        {
            if (this._person != value)
            {
                this._person = value;
                RaisePropertyChanged("Person");
            }
        }
    }

XAML:

<ListBox ItemsSource="{Binding Path=Person.ProjectList,UpdateSourceTrigger=PropertyChanged}" AlternationCount="2" ItemContainerStyle="{StaticResource CustomListBoxItemStyle}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <TextBlock>
                            <TextBlock.Text>
                                <MultiBinding StringFormat="{}{0} - {1}">
                                    <Binding Path="Name" />
                                    <Binding Path="Number" />
                                </MultiBinding>
                            </TextBlock.Text>
                            </TextBlock>
                            <TextBlock>
                            <TextBlock.Text>
                                <MultiBinding StringFormat="{}{0} - {1}">
                                    <Binding Path="StartDate" />
                                    <Binding Path="EndDate" />
                                </MultiBinding>
                            </TextBlock.Text>
                            </TextBlock>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

Customlist类:

public class ProjectList : DeletableSupport, IEnumerator, IEnumerable
{
    private IList<Project> _pList;

    private int _position;

    public ProjectList()
    {
        this._pList = new ActivatableList<Project>();
        this._position = -1;
    }

    public void Add(Project p)
    {
        Activate(ActivationPurpose.Write);
        this._pList.Add(p);
    }

    public void Remove(Project p)
    {
        Activate(ActivationPurpose.Write);
        this._pList.Remove(p);
    }

    public int Count()
    {
        Activate(ActivationPurpose.Read);
        return this._pList.Count();
    }

    public bool Contains(Project p)
    {
        Activate(ActivationPurpose.Read);
        return this._pList.Contains(p);
    }

    public Project this[int i]
    {
        get
        {
            Activate(ActivationPurpose.Read);
            return this._pList[i];
        }
        set
        {
            Activate(ActivationPurpose.Write);
            this._pList[i] = value;
        }
    }

    public static ProjectList operator +(ProjectList pList, Project p)
    {
        pList.Add(p);
        return pList;
    }

    public static ProjectList operator -(ProjectList pList, Project p)
    {
        pList.Remove(p);
        return pList;
    }

    #region IEnumerable Members

    public IEnumerator GetEnumerator()
    {
        Activate(ActivationPurpose.Read);
        return (IEnumerator)this;
    }

    #endregion

    #region IEnumerator Members

    public object Current
    {
        get
        {
            try
            {
                Activate(ActivationPurpose.Read);
                return this._pList[_position];
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }

    public bool MoveNext()
    {
        Activate(ActivationPurpose.Read);
        this._position++;
        if (_position < this._pList.Count)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public void Reset()
    {
        Activate(ActivationPurpose.Write);
        _position = -1;
    }

    #endregion
}

Activate来自db4o,ActivatableList实现IList

1 个答案:

答案 0 :(得分:3)

我会在这里冒险猜测,只是为了测试我的通灵调试技巧:)

ListBox / ListView正在使用IEnumerable.Any()(或一些等价物)来测试列表是否为空。这是返回true,因此它使用您的IEnumerable实现实际迭代列表。

请注意,它没有在您的类上调用reset,这意味着将跳过Any()调用检索到的第一个元素。

通常在IEnumerable上调用GetEnumerator将为您的类返回一个新的IEnumerator实例,但您的实际列表实现包含枚举器的所有状态。您是否考虑过如果您第二次将此列表传递给ListBox会发生什么?我认为你根本看不到任何东西。

好的,那么如何解决这个问题呢?好吧,根据您拥有的代码,只要有人调用GetEnumerator(),您就可以调用Reset()。 但是你所拥有的实现不是线程安全的(现在可能不是问题,但是谁知道将来如何使用它?)。如果你真的不想使用像ObservableCollection这样的东西来存储你的项目列表,我至少会看看从GetEnumerator方法中返回一个单独的IEnumerator实例,其中包含枚举过程的所有状态。