2

I developed an application on Windows 10 Universal App who use MVVM but I have a big problem with it.
I would add an ObservableCollection item(created on a second window) to the MVVM and then, show the new item on the ListView of MainPage but it doesn't refresh!

The 2 windows are always open

https://i.stack.imgur.com/WSo6v.jpg

The code of MVVMList.cs

public class MVVMList : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private ObservableCollection<THEFile> onglets_cache = new ObservableCollection<THEFile>();
    public ObservableCollection<THEFile> onglets_list
    {
        get
        {
            return onglets_cache;
        }

        set
        {
            onglets_cache = value;
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this,
                    new PropertyChangedEventArgs("onglets_list"));
        }
    }

    public MVVMList()
    {
        onglets_list = new ObservableCollection<THEFile>();
        Fonctions fonctions = new Fonctions();
        fonctions.LoadOnglets(onglets_cache);

    }

}

The code of the second page(always open) - CreateFile.xaml.cs

    private void create_butt_Click(object sender, RoutedEventArgs e)
    {
        Fonctions fonc = new Fonctions(); MVVMList main = new MVVMList();
        fonc.SetupNew(main.onglets_list, "test" + ".php", "");
    }

    //SetupNew on Fonctions.cs
    public async void SetupNew(ObservableCollection<THEFile> list, string name, string content)
    {
        FolderPicker folderpick = new FolderPicker();
        folderpick.ViewMode = PickerViewMode.List;
        folderpick.FileTypeFilter.Add(".html"); folderpick.FileTypeFilter.Add(".htm"); folderpick.FileTypeFilter.Add(".HTML");
        folderpick.FileTypeFilter.Add(".php"); folderpick.FileTypeFilter.Add(".PHP");
        folderpick.FileTypeFilter.Add(".css"); folderpick.FileTypeFilter.Add(".CSS");
        folderpick.FileTypeFilter.Add(".js"); folderpick.FileTypeFilter.Add(".JS");

        StorageFolder storage_file = await folderpick.PickSingleFolderAsync();
        if (storage_file != null)
        {
            MainPage vm = new MainPage();
            list.Add(new THEFile { NameOfFile = name, PathOfFile = storage_file.Path + "\\" + name, CodeOfFile = content, already_opened = false, line = 0 });
            string path = storage_file.Path + @"\" + name;
            StorageFile file_create = await storage_file.CreateFileAsync(name, CreationCollisionOption.GenerateUniqueName);
            Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(file_create);
            SaveOnglets(list);
        }
    }

And on the MainPage.xaml (always open)

...
<ListView x:Name="onglets" x:FieldModifier="public" ItemTemplate="{StaticResource Templa}" ItemsSource="{Binding onglets_list}" SelectionChanged="onglets_SelectionChanged" Margin="0,117,0,57" Visibility="Visible" ContainerContentChanging="onglets_ContainerContentChanging">
...

Thank you!

MatthewD
  • 6,719
  • 5
  • 22
  • 41
Yoshi_Gris
  • 21
  • 2

2 Answers2

0

In your XAML, try using a Collection View Source.

Add this to the top of your xaml:

<Page.Resources>
    <CollectionViewSource x:Name="MakesCollectionViewSource" IsSourceGrouped="True"/>
</Page.Resources>

Set your ListView:

ItemsSource="{Binding Source={StaticResource MakesCollectionViewSource}}"

Then in your code when you have a List of items assign it using

MakesCollectionViewSource.Source = /* Some List<GroupInfoList<object>> that is generated from onglets_list*/

I create my List like this but it may not be relevant because this is to make all of my object names alphabetical:

    internal List<GroupInfoList<object>> GetGroupsByLetter()
    {
        var groups = new List<GroupInfoList<object>>();

        var query = from item in MakeList
                    orderby ((Make)item).MakeName
                    group item by ((Make)item).MakeName[0] into g
                    select new { GroupName = g.Key, Items = g };
        foreach (var g in query)
        {
            var info = new GroupInfoList<object>();
            info.Key = g.GroupName;
            foreach (var item in g.Items)
            {
                info.Add(item);
            }

            groups.Add(info);
        }

        return groups;
    }

public class GroupInfoList<T> : List<object>
{
    public object Key { get; set; }

    public new IEnumerator<object> GetEnumerator()
    {
        return (System.Collections.Generic.IEnumerator<object>)base.GetEnumerator();
    }
}

where MakeList is my observable collection and Make are the objects in the collection and MakeName is a string I am trying to alphabetize

And then call using

MakesCollectionViewSource.Source = GetGroupsByLetter();
Seth Kitchen
  • 1,526
  • 19
  • 53
0

If I understand your code and requirements correctly, I think part of the problem is that you "new up" your MVVMList and your MainPage everytime you click the create button.

So, without getting into suggestions about using MVVM Light and an IOC container, you could quickly accomplish what you're trying to do by making your MVVMList class a singleton and having your MainPage use it for a data context. When your other window adds to the MVVMList.onglets collection, it will be immediately reflected in your currently open MainPage. Let me know if you need some code snippets. Good luck!

[Edit below]

I had a few minutes left on lunch, so here is an over-simplified example. Again, without getting into what MVVM is and is not. Personally, I would do this differently, but that would be outside the scope of your question. Full disclosure - this is in WPF, but same logic applies, I just don't have Windows 10 on the PC that I'm using. I also simplified the collection to be of type string. This is not intended to copy/paste into your code as it will not work in your example - but should easily transfer.

MVVMList class:

    public class MVVMList: INotifyPropertyChanged
        {
    //Singleton section
            private static MVVMList instance;
            private MVVMList() { }
            public static MVVMList Instance
            {
                get
                {
                    if (instance == null)
                    {
                        instance = new MVVMList();
                    }
                    return instance;
                }
            }
 //end singleton section           
            private ObservableCollection<string> _onglets = new ObservableCollection<string>();
            public ObservableCollection<string> Onglets
            {
                get { return _onglets; }
                set
                {
                    if (_onglets != value)
                    {
                        _onglets = value;
                        if (PropertyChanged != null)
                            PropertyChanged.Invoke(this,
                                new PropertyChangedEventArgs("onglets_list"));
                    }
                }
            }

    //INotify implementation 
            public event PropertyChangedEventHandler PropertyChanged;
        }

MainPage:

<ListView x:Name="onglets" x:FieldModifier="public" ItemsSource="{Binding Onglets}" />

MainPage.cs:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = MVVMList.Instance;
            Loaded += MainWindow_Loaded;
        }

        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            var x = new CreateWindow();
            x.Show();
        }
    }

CreateWindow.cs:

private void CreateButton_Click(object sender, RoutedEventArgs e)
        {
            if (!string.IsNullOrEmpty(StringTextBox.Text))
            {
                MVVMList.Instance.Onglets.Add(StringTextBox.Text);
            }
        }
Mark W
  • 1,050
  • 7
  • 15
  • Thank you for your answer ! When i test your code, i see this error: " Unable to cast COM object of type 'System.Collections.Specialized.NotifyCollectionChangedEventHandler' to class type " on CreateFile.xaml.cs, do you know why ? :( – Yoshi_Gris Oct 07 '15 at 17:55
  • Without seeing all of the code that you have, it is hard to tell. Google tells me that it may need to be more explicitly cast. http://stackoverflow.com/questions/12326069/invalidcastexception-with-share-target-on-windows-8 – Mark W Oct 09 '15 at 18:50