【问题标题】:UWP Binding to Observable Collection of UserControl not workingUWP绑定到用户控件的可观察集合不起作用
【发布时间】:2016-12-19 23:40:53
【问题描述】:

我有这个页面:NewsPage

<Page
x:Class="TouchTypeRacing.Views.NewsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TouchTypeRacing.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:TouchTypeRacing.Controls"
xmlns:models="using:TouchTypeRacing.Models"
DataContext="{Binding}"
mc:Ignorable="d">

<Grid Background="White">
    ....
    <ScrollViewer Grid.Row="1"
                  VerticalScrollBarVisibility="Auto"
                  Margin="5,10,5,0">
        <ItemsControl ItemsSource="{Binding Posts}"
                      x:Name="itemsControl">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Vertical"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate x:DataType="models:Post">
                    <controls:Post/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>
</Grid>
</Page>

页面的数据上下文绑定到视图模型。 PageViewmModel
ItemsControl 数据模板是 Post 控件。
页面上ItemsControlItemsSource 绑定到viewmodel 的Posts 属性。

public NewsPage()
{
    this.InitializeComponent();

    _viewModel = new NewsPageViewModel();
    DataContext = _viewModel;           
}

然后,视图模型:

public class NewsPageViewModel
{
    private ObservableCollection<Post> _posts = new ObservableCollection<Post>();
    public ObservableCollection<Post> Posts { get { return _posts; } }
    public NewsPageViewModel()
    {
        GetPosts(_posts);
    }
    public static void GetPosts(ObservableCollection<Post> posts)
    {
        posts.Clear();
        posts = new ObservableCollection<Post>
        {
            new Post
            {
                Id = "1",
                DateTime = DateTime.Today,
                User = Application.CurrentUser,
                Likes = 10,
                ImagePath = Application.CurrentUser.ImagePath,
                Message = "Test message",
                Comments = new ObservableCollection<Comment>
                {
                    new Comment {Id= "1", Content="Comment1", User = Application.CurrentUser },
                    new Comment {Id= "2", Content="Comment2", User = Application.CurrentUser },
                    new Comment {Id= "3", Content="Comment3", User = Application.CurrentUser },
                    new Comment {Id= "4", Content="Comment4", User = Application.CurrentUser },
                },
                Last2Comments = new List<Comment>
                {
                    new Comment {Id= "3", Content="Comment3", User = Application.CurrentUser },
                    new Comment {Id= "4", Content="Comment4", User = Application.CurrentUser },
                }
            }
        };
    }

ItemsControl 显示为空。 我做错了什么?

【问题讨论】:

    标签: c# wpf data-binding uwp uwp-xaml


    【解决方案1】:

    如果您想继续切换集合,NewsPageViewModel 必须实现 INotifyPropertyChanged 并在您更改集合实例时引发 PropertyChanged。这是怎么回事。我还在下面提供了一个更简单的“快速修复”解决方案。

    public class VIewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        public void OnPropertyChanged([CallerMemberName] String propName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        }
    }
    
    public class NewsPageViewModel : ViewModelBase
    {
        public NewsPageViewModel()
        {
            Posts = GetPosts();
        }
    
        private ObservableCollection<Post> _posts;
        public ObservableCollection<Post> Posts
        {
            get { return _posts; }
            set {
                _posts = value;
                OnPropertyChanged();
            }
        }
    
        protected ObservableCollection<Post> GetPosts()
        {
            //  do stuff to get posts, return new ObservableCollection<Post>
        }
    }
    

    快速修复

    更简单的方法是从集合实例开始,这样 UI 在第一次(在这种情况下,仅)获取 Posts 的值时获得一些东西,保持相同的集合。但是,如果没有INotifyPropertyChanged,您将遇到无数这样的问题。尝试在没有它的情况下使用 WPF 确实是一种自我惩罚的练习。

    ObservableCollection<Post> _posts = new ObservableCollection<Post>();
    
    public ObservableCollection<Post> Posts { get { return _posts; } }
    public NewsPageViewModel()
    {
        GetPosts(_posts);
    }
    public static void GetPosts(ObservableCollection<Post> posts)
    {
        posts.Clear();
        //  ...get posts
    }
    

    ObservableCollection 的特别之处在于它实现了INotifyCollectionChanged,当您从集合中添加或删除项目时,它将通知 UI ——但 UI 必须知道要侦听哪个集合以进行更改。

    【讨论】:

    • 仍然没有显示任何内容。我已经在您的快速修复中编辑了 Viewmodel。检查编辑
    • @shadowCODE 你调用posts.Clear() 然后你把它扔掉并用一个新的集合替换参数。不要那样做。这对您执行此操作的方法之外的任何内容都没有影响。将帖子放在旧集合中。您必须、必须、必须、必须保持相同的集合才能使该修复工作。在该代码中,您开始使用的集合是 UI 永远知道的唯一集合。所以这是帖子必须进入的地方。这就是为什么这不是一个很好的解决方案的原因之一。
    • @shadowCODE 见上文“自我惩罚练习”。
    • GetPosts() 中执行posts.Add(new Post()) - 保持与您所说的相同的帖子 - 使应用程序崩溃。
    • @shadowCODE 有什么异常? posts 是否为空?
    【解决方案2】:

    我还不能添加 cmets...所以:

    在 NewsPageViewModel 的构造函数中,您初始化一个新的(但为空的)ObservableCollection。

    如果您没有在 GetPost 方法中添加元素,_posts 将保持为空。

    【讨论】:

      猜你喜欢
      • 2017-09-28
      • 1970-01-01
      • 2011-11-16
      • 2010-11-18
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-05
      相关资源
      最近更新 更多