Wiktor
Wiktor

Reputation: 856

Why my second ObservableCollection is getting update?

I have two ObservableCollections filled with Items (that Items are also ObservableCollecions filled with other types of object) of the same type.

_TreeViewBase - First ObservableCollection is 'base' with all data.

_TVData - Second ObservableCollection should store only 'needed' items, I have also TreeView with ItemSource binded to TVData.

Function FillAliasTreeView is used only to fill _TreeViewBase with data so I will not paste code here.

When at the begining of program I assign _TreeViewBase to _TVData in LoadSideBar() function everything is ok. Both of ObservableCollection are storing all data.

But when I search something ( and my TVData is modified in SearchBox_TextChanged() ) then It's seems that also _TreeViewBase is modified.

How it is possible? Did I made some major mistake in my code?

My class ( almost full code ) :

public partial class SideBar : Page, INotifyPropertyChanged
{
    private ObservableCollection<ConnectionModel> _TreeViewBase;
    private ObservableCollection<ConnectionModel> _TVData ;



    public SideBar()
    {
        TreeViewBase = new ObservableCollection<ConnectionModel>( ConnectionUtilities.LoadObservableConnections() ) ;
        TVData       = new ObservableCollection<ConnectionModel>();

        InitializeComponent();


        DataContext = this;

        var loadSideBar = Task.Factory.StartNew( async () => { await LoadSideBar();   } );
        loadSideBar.Wait();

        OnPropertyChanged("TVData");
    }


    public async Task LoadSideBar()
    {
        // this function is used to fill my _TreeViewBase  
        await FillAliasTreeView();

        TVData = TreeViewBase;
        OnPropertyChanged("TVData");

    }

     private async void SearchBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        string newsearchText = SearchBox.Text;

        if ( (newsearchText == "" || newsearchText == "Search..." || newsearchText.Length < 3  )  ) 
        {

            TVData.Clear();
            TVData = null;

            MessageBox.Show( (TVData == null).ToString() + " " + TreeViewBase.Count.ToString());


            TVData = new ObservableCollection<ConnectionModel>( TreeViewBase );

            AliasTree.ItemsSource = TVData ;

            AliasTree.UpdateLayout();

            return;
        }

        searchText = SearchBox.Text;


        if (TVData != null)
        {
            await Dispatcher.InvokeAsync(
            () =>
            {
                foreach (ConnectionModel cm in TVData.ToList<ConnectionModel>())
                {
                    foreach (SchemaModel sm in cm.schemas.ToList<SchemaModel>())
                    {
                        foreach (SchemaCollection sc in sm.schema_collections.ToList<SchemaCollection>())
                        {
                            try
                            {
                                ObservableCollection<TableModel> octm = (ObservableCollection<TableModel>)sc.collection;

                                for (int i = 0; i < octm.Count; i++)
                                {
                                    if (!(sc.collection as ObservableCollection<TableModel>)[i].TABLE_NAME.Contains(searchText))
                                    {
                                        (sc.collection as ObservableCollection<TableModel>).RemoveAt(i);
                                        i = i - 1;
                                    }
                                    Dispatcher.InvokeAsync( () => OnPropertyChanged("tables") ) ;
                                }
                                Dispatcher.InvokeAsync(() => OnPropertyChanged("collection") );
                            }
                            catch (Exception exc) { }
                        }
                        Dispatcher.InvokeAsync(() => OnPropertyChanged("schemas") );
                    }
                    Dispatcher.InvokeAsync(() => OnPropertyChanged("TVData"));
                }
                Dispatcher.InvokeAsync(() => OnPropertyChanged("TVData"));
            });

            await Dispatcher.InvokeAsync(() => ExpandAll(AliasTree));
        }
    }


    private void ExpandAll( ItemsControl root )
    {
        if ( root != null )
        {
            foreach (var subItem in root.Items)
            {
                if (subItem != null)
                {
                    ExpandAll( (TreeViewItem)root.ItemContainerGenerator.ContainerFromItem(subItem) );
                    try
                    {
                        if (((TreeViewItem)root.ItemContainerGenerator.ContainerFromItem(subItem) as TreeViewItem) != null )
                            ((TreeViewItem)root.ItemContainerGenerator.ContainerFromItem(subItem) as TreeViewItem).IsExpanded = true;
                    }
                    catch (Exception exc) { };
                }
            }

            AliasTree.UpdateLayout();
        }
    }

Thank You for any suggestions.

Upvotes: 0

Views: 52

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 457037

In your constructor, you set TVData and TreeViewBase to two different instances of ObservableCollection<>. But then this line:

TVData = TreeViewBase;

makes them refer to the same instance. The old TVData observable collection is discarded, and both of those variables now refer to the same observable collection.

This is just how reference types work.

Upvotes: 5

Related Questions