-1

After knowing about ObservableCollection in UWP i try it out immediately, working in 1 page is simple enough. But when i try to show the gridview bind to ObservableCollection in one page, and call Add data to that ObservableCollection from another page i ran into error. I dont know if my searching skill is still too low or what but after 30m searching i found no solution. Hoping for some guides here. Here my code:

MainPage.xaml

<Grid.RowDefinitions>
        <RowDefinition Height="50*"></RowDefinition>
        <RowDefinition Height="400*"></RowDefinition>
    </Grid.RowDefinitions>
    <Button x:Name="btnNewWindow" Content="Show add window" FontSize="20" Grid.Row="0" Click="btnNewWindow_Click"></Button>
    <ListView x:Name="listView" Grid.Row="1">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="data:Test" x:Name="templateGrid">
                <StackPanel x:Name="stackPanel"  Orientation="Vertical" HorizontalAlignment="Center">
                    <TextBlock FontSize="18" Text="{x:Bind id}" HorizontalAlignment="Center"></TextBlock>
                    <TextBlock FontSize="10" Text="{x:Bind name}" HorizontalAlignment="Center"></TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

MainPage.xaml.cs

SQLite.Net.SQLiteConnection conn;
    private List<Test> tempList;
    public static ObservableCollection<Test> testList;
    public static string _bookID = "";
    private string bookTitle = "";

    public MainPage()
    {
        this.InitializeComponent();
        string path = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "testDB.db");
        conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), path);
        conn.CreateTable<Test>();
        tempList = conn.Query<Test>(@"select * from Test");
        testList = new ObservableCollection<Test>(tempList);
        listView.ItemsSource = testList;
    }

    async private void btnNewWindow_Click(object sender, RoutedEventArgs e)
    {
        CoreApplicationView newView = CoreApplication.CreateNewView();
        int view_id = 0;

        await newView.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            Frame frame = new Frame();
            frame.Navigate(typeof(AddPage), null);
            Window.Current.Content = frame;
            Window.Current.Activate();

            view_id = ApplicationView.GetForCurrentView().Id;

            var app_view = ApplicationView.GetForCurrentView();
            app_view.SetPreferredMinSize(new Size(500, 400));

            ApplicationView.PreferredLaunchWindowingMode = Windows.UI.ViewManagement.ApplicationViewWindowingMode.PreferredLaunchViewSize;
            ApplicationView.PreferredLaunchViewSize = new Size(500, 400);
            app_view.Title = $"Add page";
        });

        await ApplicationViewSwitcher.TryShowAsStandaloneAsync(view_id);
    }

AddPage.xaml

<Grid.RowDefinitions>
        <RowDefinition Height="70*"></RowDefinition>
        <RowDefinition Height="70*"></RowDefinition>
        <RowDefinition Height="70*"></RowDefinition>
    </Grid.RowDefinitions>
    <TextBox x:Name="txtID" Header="ID" Margin="20" Grid.Row="0"></TextBox>
    <TextBox x:Name="txtName" Header="Name" Margin="20" Grid.Row="1"></TextBox>
    <Button x:Name="btnAdd" Margin="20" Grid.Row="2" Content="Add" Click="btnAdd_Click"></Button>

AddPage.xaml.cs

SQLite.Net.SQLiteConnection conn;
    public AddPage()
    {
        this.InitializeComponent();
        string path = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "testDB.db");
        conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), path);
    }

    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
        string id = txtID.Text;
        string name = txtName.Text;
        MainPage.testList.Add(new App2.Test{ id = id, name = name });//Error here
        conn.Execute(@"insert into Test values (?,?)", id, name);
        Window.Current.Close();
    }

Test class:

public class Test
{
        public string id { get; set; }
        public string name { get; set; }

        public Test(){}
}

Error:

An exception of type 'System.InvalidCastException' occurred in System.ObjectModel.dll but was not handled in user code Additional information: Unable to cast COM object of type 'System.Collections.Specialized.NotifyCollectionChangedEventHandler' to class type

Thanks in advance. Sorry if duplicated.

Dant
  • 89
  • 9
  • I believe the problem may be in the btnAdd_Click event method. If string id correlates with int view_id, it may simply need to be parsed. i.e. instead of string id = 0; int.TryParse(txtID.Text, out id). If this does not fix the problem, can you post your Test class fields and properties pertaining to id and name? – David Cardinale Jan 07 '17 at 11:26
  • @David Cardinale : Here, i added the test class code to the question. Sorry i forgot. – Dant Jan 07 '17 at 13:50
  • I believe the problem is in this line: tempList = conn.Query(@"select * from Test"); tempList is expecting a type. I would create a separate method that performs this query and returns a List. Unfortunately I have to run, but I hope this helps a little. – David Cardinale Jan 07 '17 at 14:20

2 Answers2

2

I can reproduce your issue. I will report it using our internal channel.

As a temporary workaround, we should be able to use the Popup to replace the new View. Also we can insert the item to the ObservableCollection without any exception.

For example:

The XAML code:

<Popup Name="MyPopup">
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="70*"></RowDefinition>
            <RowDefinition Height="70*"></RowDefinition>
            <RowDefinition Height="70*"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBox x:Name="txtID" Header="ID" Margin="20" Grid.Row="0"></TextBox>
        <TextBox x:Name="txtName" Header="Name" Margin="20" Grid.Row="1"></TextBox>
        <Button x:Name="btnAdd" Margin="20" Grid.Row="2" Content="Add" Click="btnAdd_Click"></Button>
    </Grid>
</Popup>

The code behind:

private void btnNewWindow_Click(object sender, RoutedEventArgs e)
{
    MyPopup.IsOpen = true;
}

private void btnAdd_Click(object sender, RoutedEventArgs e)
{
    string id = txtID.Text;
    string name = txtName.Text;
    testList.Add(new App2.Test { id = id, name = name });
    conn.Execute(@"insert into Test values (?,?)", id, name);
    MyPopup.IsOpen = false;
}
Jayden
  • 3,276
  • 1
  • 10
  • 14
0

There are several things I can note for you:

If your problem is not the cross-threading, could you clarify where and when this exception occurs? e.g. on launching the add-window or closing, and which line of code.

apologies for not being able to comment this, lack of reputation :/

Community
  • 1
  • 1
Pluriscient
  • 125
  • 1
  • 10
  • exception when i click on button Add of second page. Marked in the AddPage.xaml.cs. These thread and background are new to me, got to research about this. – Dant Jan 07 '17 at 14:35
  • Ah, well if you don't receive a compile-time error with that I strongly suspect it has to do with the cross-threading – Pluriscient Jan 07 '17 at 15:05