首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >UWP将IEnumerable转换为ObservableCollection (x:Bind)

UWP将IEnumerable转换为ObservableCollection (x:Bind)
EN

Stack Overflow用户
提问于 2017-03-15 18:29:28
回答 1查看 819关注 0票数 1

好的,我有一个IEnumerable集合,我把它转换成一个ListView

当应用程序运行时,我希望每当这个IEnumerable列表发生变化时,我的listview也会被更新。即使在使用INotifyPropertyChanged时也不是这样,所以我决定转向将IEnumerable转换为ObservableCollection

我发现存在的演员是:

代码语言:javascript
运行
复制
myCollection = new ObservableCollection<object>(the_list);

这在不同的问题上会很好,但在我的例子中,我是x:将它绑定到listview,每次我使用上面的代码运行该方法时,都会创建一个新的引用,而绑定将不能工作(它不能工作)。是这样吗?如果是的话,我该如何解决这个问题?如果没有,我做错了什么?谢谢。

目前,我的代码如下所示:

代码语言:javascript
运行
复制
public ObservableCollection<IMessage> MessageList;

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

什么对我有用:

多亏了玛丽安?多林斯克的回答,现在一切都成功了。我提出了一些我的代码,以便更清楚地说明我所做的事情:

代码语言:javascript
运行
复制
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中的代码:

代码语言:javascript
运行
复制
<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>

再次感谢你的帮助:)

EN

Stack Overflow用户

回答已采纳

发布于 2017-03-15 19:40:50

它不是因为ObservableCollection的工作方式而更新的-它只通知集合中的更改,但是当您在SetMessages方法中分配MessageList时,您正在创建ObservableCollection的新实例,而ListView.Source是指向ObservableCollection的原始绑定实例。

而且,我看到MessageList不是一个属性,而是一个字段。字段不适用于绑定。

您有四个选项可以实现ListView的更新

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

代码语言:javascript
运行
复制
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集合,则可以直接从代码中设置ListViewItemsSource属性:

代码语言:javascript
运行
复制
private async Task SetMessages()
{
     YourListView.ItemsSource = await channel.GetMessagesAsync(20).Flatten();
}

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

代码语言:javascript
运行
复制
private async Task SetMessages()
{
    MessageList = new ObservableCollection<IMessage>(await channel.GetMessagesAsync(20).Flatten());
    Bindings.Update();
}

4)您可以在页面上实现INotifyPropertyChanged或为MessageList创建DependencyProperty,然后将其绑定到Mode设置为OneWay

代码语言:javascript
运行
复制
<ListView ItemsSource="{x:Bind MessageList, Mode=OneWay}">

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

编辑:

我认为问题就在这两条线上:

代码语言:javascript
运行
复制
messageList.Add(arg);
messageList.Remove(messageList[NumOfMessages - 1]);

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

票数 2
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42817919

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档