Ian Vink
Ian Vink

Reputation: 68750

Using ResourceDictionary.MergedDictionaries in App.xaml

In VS2017 with Xamarin

In my app.xaml I have a MergedDictionary which references a xaml containing my DataTemplate. It isn't being recognized by a content page. If I move the DataTemplate into the app.xaml it works fine.

How do I get the <ResourceDictionary.MergedDictionaries> to recognize the StaticResource defined in the CellTemplates.xaml ?

My App.xaml:

<Application.Resources>
   <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Resources/CellTemplates.xaml"/>
        </ResourceDictionary.MergedDictionaries>
   ....

My CellTemplates.xaml:

 <ResourceDictionary
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <DataTemplate x:Key="CustomerTemplate">
    <ViewCell Height="100">
          <StackLayout VerticalOptions="FillAndExpand">
     ....

My Content Page:

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:local="clr-namespace:Muffin"
         x:Class="Muffin.MainPage">
<ScrollView>
    <ListView ItemsSource="{Binding Customers}" 
              HasUnevenRows="True" 
              ItemTemplate="{StaticResource CustomerTemplate}">
    </ListView>
....

Upvotes: 6

Views: 3077

Answers (2)

Makeman
Makeman

Reputation: 944

It's possible to create custom ResourceDictionary with multiple merging support.

See: https://github.com/Makeloft/Ace/blob/master/Ace.Zest/Markup/ResourceDictionary.cs

internal static class MergeExtensions
{
    internal static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
    {
        foreach (var item in items) action(item);
    }

    internal static void Merge<TKey, TValue>(this IDictionary<TKey, TValue> targetDictionary,
        IEnumerable<KeyValuePair<TKey, TValue>> sourceItems)
    {
        var targetItems = targetDictionary.ToArray();
        sourceItems.ForEach(i => targetDictionary[i.Key] = i.Value);
        targetItems.ForEach(i => targetDictionary[i.Key] = i.Value); // override merged by local values
    }
}

public class ResourceDictionary : Xamarin.Forms.ResourceDictionary
{
    public ResourceDictionary()
    {
        MergedDictionaries = new ObservableCollection<Xamarin.Forms.ResourceDictionary>();
        MergedDictionaries.CollectionChanged += (sender, args) =>
            (args.NewItems ?? new List<object>()).OfType<Xamarin.Forms.ResourceDictionary>()
            .ForEach(this.Merge);
    }

    public ObservableCollection<Xamarin.Forms.ResourceDictionary> MergedDictionaries { get; }
}

Usage

<Application.Resources>
    <m:ResourceDictionary>
        <m:ResourceDictionary.MergedDictionaries>
            <local:AppConverters />
        </m:ResourceDictionary.MergedDictionaries>

        <AnotherResource x:Key="Key1" />
    </m:ResourceDictionary>
</Application.Resources>

Upvotes: 3

pinedax
pinedax

Reputation: 9346

You are trying to use a functionality that is not currently available in Xamarin.Forms and that's the use of multiple Merged Dictionaries. At the moment you can only have a single MergedDictionary

Try this in your code:

App.xaml

<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    xmlns:local="clr-namespace:Muffin"
    x:Class="Muffin.App">
    <Application.Resources>
        <ResourceDictionary MergedWith="local:CellTemplates">
                  ...
            <!--YOUR APP LEVEL STYLES -->
                  ...
        </ResourceDictionary>
    </Application.Resources>
</Application>

Note that to merge the Resource is not used the physical file location instead it's used the full namespace + class name.

Good news is that the possibility of merging more than one ResourceDictionary in Xamarin is under development and it should be available any soon. If you want to follow the advances of this feature subscribe to this thread in github.

Hope this helps.-

Upvotes: 2

Related Questions