none
Why it does not update the UI while I bind the ObservableCollection? RRS feed

  • Question

  • Here is XAML:

    <Window x:Class="WpfApp1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <ItemsControl x:Name="IC" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Border BorderBrush="#cecece" BorderThickness="0,0,0,1" Background="Transparent" >
                            <TextBlock Text="{Binding ABC}"></TextBlock>
                        </Border>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel></VirtualizingStackPanel>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
            <Button Grid.Column="1" Click="Button_Click"></Button>
        </Grid>
    </Window>

    And here is code-behind:

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;

    namespace WpfApp1
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();            
                IC.SetBinding(ItemsControl.ItemsSourceProperty, new Binding { Source = CM.TopCollection });            
            }
            public CollectionModel CM = new CollectionModel();
            public class TestModel {
                public string ABC { get; set; }
            }
            public class CollectionModel : ObservableCollection<TestModel>, INotifyPropertyChanged
            {
                public CollectionModel()
                {
                    CollectionChanged += MyCollection_CollectionChanged;
                }          

                private void MyCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
                {
                    OnPropertyChanged(new PropertyChangedEventArgs(nameof(TopCollection)));
                }
                public IEnumerable<TestModel> TopCollection => this.Take(10);
            }

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                CM.Add(new TestModel() {ABC= Guid.NewGuid().ToString() });
            }
        }
    }

    When I clicked the button, the Collection add successfully but the UI not.

    Why it turns out to be this and how can I solve it? Thank you.

    Thursday, August 15, 2019 2:14 PM

Answers

  • Try this:

    IC.SetBinding( ItemsControl.ItemsSourceProperty, new Binding( nameof( CM.TopCollection ) ) { Source = CM } );
    
    

     

    • Marked as answer by mywatermelon Friday, August 16, 2019 2:04 AM
    Thursday, August 15, 2019 5:12 PM

All replies

  • Try this:

    IC.SetBinding( ItemsControl.ItemsSourceProperty, new Binding( nameof( CM.TopCollection ) ) { Source = CM } );
    
    

     

    • Marked as answer by mywatermelon Friday, August 16, 2019 2:04 AM
    Thursday, August 15, 2019 5:12 PM
  • Try this:

    IC.SetBinding( ItemsControl.ItemsSourceProperty, new Binding( nameof( CM.TopCollection ) ) { Source = CM } );
    

     

    Thank you. It works. But would you please tell me what's the difference between my code and yours.

    I wanna know the reason which can not update the UI also.

    Friday, August 16, 2019 1:21 AM
  • Hi     mywatermelon,

    Your SetBinding operation has not set specified Property access path.

    Usually, we will declare Binding type variables and create instances, then use binding.Source = videmodel to specify data sources for Binding instances, and finally use binding.Path = new Property Path ("Name") to specify access paths for Binding.

    // Make a new source.
    MyData myDataObject = new MyData(DateTime.Now);      
    Binding myBinding = new Binding("MyDataProperty");
    myBinding.Source = myDataObject;

    For more detailed:

    How to: Create a Binding in Code

    Besides, It would be appreciated if you could close the thread by marking helpful posts as an answer. This will help other members to find the solution quickly if they have faced the similar issue. If you have a new question you can start a new thread  with all necessary code snippets for anyone else to be able to reproduce your issue from scratch along with a detailed description about the results including any exception messages.

    Thank you for your understanding.

    Best regards

    Yong Lu

     

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, August 16, 2019 2:03 AM
    Moderator
  • Hi     mywatermelon,

    Your SetBinding operation has not set specified Property access path.

    Usually, we will declare Binding type variables and create instances, then use binding.Source = videmodel to specify data sources for Binding instances, and finally use binding.Path = new Property Path ("Name") to specify access paths for Binding.

    // Make a new source.
    MyData myDataObject = new MyData(DateTime.Now);      
    Binding myBinding = new Binding("MyDataProperty");
    myBinding.Source = myDataObject;

    For more detailed:

    How to: Create a Binding in Code

    Besides, It would be appreciated if you could close the thread by marking helpful posts as an answer. This will help other members to find the solution quickly if they have faced the similar issue. If you have a new question you can start a new thread  with all necessary code snippets for anyone else to be able to reproduce your issue from scratch along with a detailed description about the results including any exception messages.

    Thank you for your understanding.

    Best regards

    Yong Lu

     

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thank you very much.
    Friday, August 16, 2019 2:05 AM