1

好的,所以我有一个IEnumerable集合,我将其x:Bind放入ListView.

当应用程序运行时,只要此IEnumerable列表更改,我listview也希望更新。即使在使用时也并非如此INotifyPropertyChanged,因此我决定将其转换IEnumerableObservableCollection.

我发现存在的演员是:

myCollection = new ObservableCollection<object>(the_list);

这在不同的问题中可以正常工作,但在我的情况下,我是 x:Bind this to thelistview并且每次我使用上述代码运行该方法时,都会创建一个新引用并且绑定将不起作用(它不起作用) . 那是对的吗 ?如果是,我该如何解决这个问题?如果没有,我做错了什么?谢谢你。

目前我的代码如下所示:

public ObservableCollection<IMessage> MessageList;

private async Task SetMessages()
{
    MessageList = new ObservableCollection<IMessage>(await channel.GetMessagesAsync(NumOfMessages).Flatten());
}

什么对我有用:

完全感谢 Marian Dolinský 的回答,现在一切正常。我提出了一些我的代码以使其更清楚我所做的是:

class ChatViewModel : INotifyPropertyChanged
{
    //Number of messages to have in list at once.
    private int NumOfMessages = 20;

    //Called when a user clicks on a channel.
    public async Task SelectChannel(object sender, ItemClickEventArgs e)
    {
        //Set the channel to clicked item
        channel = (SocketTextChannel)e.ClickedItem;
        //Receive the messages in the list.
        IEnumerable<IMessage> data = await channel.GetMessagesAsync(NumOfMessages).Flatten();
        //Clear the observablecollection from any possible previous messages (if for example you select another channel).
        messageList.Clear();
        //Loop and add all messages to the observablecollection
        foreach (var item in data)
        {
            messageList.Add(item);
        }
    }

    //The event handler when a message is received.
    private async Task Message_Received(SocketMessage arg)
    {
        //Calls to add message only if the message received is of interest.
        if (arg.Channel == channel)
        {
            //Sets the thread equal to the UI thread.
            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
             {
                //Adds the new message, removes the oldest to keep always 20.
                 messageList.Add(arg);
                 messageList.Remove(messageList[0]);
             });
        }
    }

    private ObservableCollection<IMessage> messageList = new ObservableCollection<IMessage>();

    public ObservableCollection<IMessage> MessageList
    {
        get
        {
            return messageList;
        }
    }
}

这是 XAML 中的代码:

<Page.DataContext>
    <vm:ChatViewModel x:Name="ChatViewModel"/>
</Page.DataContext>

                    <ListView VerticalContentAlignment="Bottom" ItemsSource="{x:Bind ChatViewModel.MessageList, Mode=OneWay}" SelectionMode="None" ItemTemplate="{StaticResource MessageListDataTemplate}">
                        <ListView.ItemContainerStyle>
                            <Style TargetType="ListViewItem">
                                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                                <Setter Property="Margin" Value="0,0,5,5"/>
                            </Style>
                        </ListView.ItemContainerStyle>
                    </ListView>

再次感谢你的帮助 :)

4

1 回答 1

2

由于ObservableCollection工作原理,它没有更新 - 它仅通知集合内部的更改,但是当您在MessageList方法SetMessages中分配ObservableCollectionListView.SourceObservableCollection

另外,我看到这MessageList不是属性,而是字段。字段不适用于绑定。

您有四种选择如何实现更新ListView

1)您可以将现有MessageList数据与新数据同步:

private async Task SetMessages()
{
    IEnumerable newData = await channel.GetMessagesAsync(20).Flatten();

    // Assuming MessageList is not null here you will sync newData with MessageList
}


2)如果您没有MessageList在其他任何地方使用该集合,则可以直接从代码中设置ItemsSource属性:ListView

private async Task SetMessages()
{
     YourListView.ItemsSource = await channel.GetMessagesAsync(20).Flatten();
}


3)由于您使用的是表达式,因此每次要刷新页面上的任何绑定时x:Bind都可以调用方法:Bindings.Update();

private async Task SetMessages()
{
    MessageList = new ObservableCollection<IMessage>(await channel.GetMessagesAsync(20).Flatten());
    Bindings.Update();
}


4)您可以INotifyPropertyChanged在页面上实现或创建DependencyPropertyMessageList然后将其与Modeset 绑定到OneWay

<ListView ItemsSource="{x:Bind MessageList, Mode=OneWay}">

我个人不推荐第四个选项。最好的选择是同步数据,因为ListView自动动画添加和删除 ListViewItems。

编辑:

我认为问题出在这两行:

messageList.Add(arg);
messageList.Remove(messageList[NumOfMessages - 1]);

因为新项目是在集合的末尾添加的,所以您要删除上次添加的项目。要删除最旧的项目,您应该使用messageList.RemoveAt(0);删除第一个位置的项目。

于 2017-03-15T19:40:50.093 回答