views:

86

answers:

2

I'm trying to figure out how to programmatically apply a theme at runtime in our Silverlight 4 application. I figured this should be as simple as loading a resource dictionary from XAML and merging it with the application's merged dictionaries. Here's my code so far:

var themeUri = new Uri(
    "OurApp;component/Themes/Classic/Theme.xaml", UriKind.Relative);
var resourceInfo = GetResourceStream(themeUri);
using (var stream = resourceInfo.Stream)
{
    using (var reader = new StreamReader(stream))
    {
        var xamlText = reader.ReadToEnd();
        var dict = XamlReader.Load(xamlText) as ResourceDictionary;
        Resources.MergedDictionaries.Add(dict);
    }
}

Unfortunately, a XamlParseException is raised during the call to XamlReader.Load:

The attachable property 'Foo' was not found in type 'Bar'.

This attached properly is properly declared, and the namespace declaration in the XAML correctly references the required namespace. The attached property XAML works just fine if loaded into the merged dictionaries declaratively through the App.xaml markup.

Here's an abbreviated copy of the XAML which I'm trying to load at runtime:

<ResourceDictionary xmlns:u="clr-namespace:Company.Product.Utils"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;
  <Style x:Key="ControlPanelStyle" TargetType="ContentControl">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="ContentControl">
          <Grid Margin="0" u:Bar.Foo="True">
            <!-- Stuff and things -->
            <ContentPresenter Content="{TemplateBinding Content}" />
          </Grid>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

Why is the reference to the attached property not working when loading XAML at runtime when it is working just fine when "statically" loaded?

A: 

I just faced this problem today and i solved it by using a Behavior... it's kind of ugly but it does the trick.

public string Title
    {
        get { return (string)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TitleProperty =
        DependencyProperty.Register("Title", typeof(string), typeof(AddressableObjectBehavior), new PropertyMetadata(null, OnTitleChanged));

    protected override void OnAttached()
    {
        AddressableObject.SetTitle(this.AssociatedObject, this.Title);
        base.OnAttached();
    }

Hope it help! Cheers! Fer Callejón.-


Hi Jacob, that's wierd, I have the assembly referenced as you said

xmlns:bsic="clr-namespace:Bsi.Ipp.Eurocodes.UI.Controls;assembly=Bsi.Ipp.Eurocodes.UI.Controls"

But, anyway, it doesn't work. The difference is that I'm loading a Canvas not a Resource, but i guess, xaml validation's should be same.

I'll try by setting this ns on the same tag where I'm going to use it.

Cheers!!

+1  A: 

I just figured out the source of the problem. In our XAML, we had declared our namespace as follows:

xmlns:u="clr-namespace:Company.Product.Utils"

It seems that although this works for statically-compiled XAML, it doesn't work for dynamically loaded XAML because when dynamically loaded, the assembly for the namespace doesn't get resolved. Once we changed the namespace declaration to this, it worked:

xmlns:u="clr-namespace:Company.Product.Utils;assembly=OurAssembly"
Jacob