BaseView

Nov 14, 2014 at 9:39 AM
Hey,

first of all, awesome framework! We really would like to integrate MtPage/Frame/Application it in our current app project. However our firsts tests discovered some issues.

Our App has a somehow special design, we use a base view where all our other views inherit from. Now we have two issues so far.
(1) TopAppBar and BottomAppBar are define in our Base and in all other views override on demand. Now the app crash at MtPage OnLoaded, because adding a resource to TopAppBar throws this Exception "element is already child of another element".
(2) We define VisualStates in our base, but those are not any longer working. They are fired by the corresponding code, but they won’t execute. No error is given here.

Let us know if we can provide any further useful information.

It would be nice if you could evaluate those issues and tell us what you think of the problems. Would be great if you could help us to find a solution!

Thanks!
BaseView
Coordinator
Nov 14, 2014 at 10:09 AM
Hi,

Thanks for using the libraries.
The changes in the paging classes are very drastic, this is why some problems may arise...
Can you provide a sample project to reproduce your issues?
Then Ill check what we can do...

Rico
Nov 14, 2014 at 3:12 PM
We are pretty busy right now, but I will try to create a reproducible demo for you when I have some time.
Dec 9, 2014 at 8:30 PM
Hi,

I am able to reproduce the problem by including a CollectionViewSource in the Page's resources and then also having an AppBar. This results in the following:
System.Exception: No installed components were detected. Element is already the child of another element.

   at System.Runtime.InteropServices.WindowsRuntime.IMap`2.Insert(K key, V value)
   at System.Runtime.InteropServices.WindowsRuntime.MapToDictionaryAdapter.Insert[K,V](IMap`2 _this, K key, V value)
   at System.Runtime.InteropServices.WindowsRuntime.MapToDictionaryAdapter.Indexer_Set[K,V](K key, V value)
   at MyToolkit.Paging.MtPage.OnLoaded(Object sender, RoutedEventArgs routedEventArgs)
Looking at MtPage.OnLoaded, it looks like the code is adding each of the MtPage's resources to the framework page's TopAppBar:
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
        {
            if (TopAppBar != null)
            {
                InternalPage.TopAppBar = TopAppBar;
                foreach (var item in Resources)
                    InternalPage.TopAppBar.Resources[item.Key] = item.Value; // exception generated here
            }

            if (BottomAppBar != null)
            {
                InternalPage.BottomAppBar = BottomAppBar;
                foreach (var item in Resources)
                    InternalPage.BottomAppBar.Resources[item.Key] = item.Value;
            }
        }
It looks to me like CollectionViewSource doesn't like being in two controls' Resources at once. What is the motivation behind foreach (var item in Resources)
InternalPage.TopAppBar.Resources[item.Key] = item.Value
?
Dec 9, 2014 at 8:45 PM
Forgot to say, I was able to overcome this by moving all the controls that were in or were derived from controls in namespace Windows.* from the page's resources to the first grid's resources:
<paging:MtPage>
 <paging:MtPage.TopAppBar>
  <AppBar ... />
 </paging:MtPage.TopAppBar>
 <paging:MtPage.Resources>
  <!-- No Windows.* namespace controls here -->
  <viewModels:MyPageModel
   x:Key="ViewModel" />
 </paging:MtPage.Resources>
 <Grid
 DataContext="{StaticResource ViewModel}">
 <Grid.Resources>
  <!-- Any desired Windows.* namespace controls here -->
  <CollectionViewSource ... />
 </Grid.Resources>
 <!-- etc etc etc -->
</paging:MtPage>
This seems to work fine for me.
Coordinator
Dec 9, 2014 at 8:51 PM
The idea is to have access to the same resources as the page...
But as it seems this may be a problem... Maybe there's another way to achieve this goal (dependency property inheritance, if this exists in WinRT).

A current solution may be to define the CollectionViewSource (which can only be at one location) in the child's resource instead in the page... but the problem must still be solved...

Ill check if theres a way to do that...
Coordinator
Dec 9, 2014 at 9:05 PM
Edited Dec 9, 2014 at 9:07 PM
I didn't find a good solution but I changed the code to:
if (TopAppBar != null)
{
    InternalPage.TopAppBar = TopAppBar;
    foreach (var item in Resources.Where(item => !(item.Value is DependencyObject)))
        InternalPage.TopAppBar.Resources[item.Key] = item.Value;
}

if (BottomAppBar != null)
{
    InternalPage.BottomAppBar = BottomAppBar;
    foreach (var item in Resources.Where(item => !(item.Value is DependencyObject)))
        InternalPage.BottomAppBar.Resources[item.Key] = item.Value;
}
so that only "shareable" objects are added to the AppBar's resources... This should fix your problem. However the CollectionViewSource cannot be used in the AppBars (I think this should not be needed).
Coordinator
Dec 9, 2014 at 9:06 PM
Can you test your original XAML code with the newest source code?