0

When setting a contentcontrols template to xaml in code behind I cant access a static resource contained in the parent xaml.

I have a contentcontrol as follows:

<ContentControl x:Name="ccMaterial">
  <ContentControl.Resources>
    <x:Array x:Key="BondListKey" Type="sys:Int32" 
             xmlns:sys="clr-namespace:System;assembly=mscorlib" />
  </ContentControl.Resources> 
</ContentControl>

then in codebehind I am setting the template as follows:

   string template = "<ControlTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>" +
     "<ComboBox Grid.Column=\"1\" Grid.Row=\"0\" ItemsSource=\"{Binding Source={StaticResource BondListKey}}\"  />" +
"</ControlTemplate>";
ccMaterial.Template = (ControlTemplate)XamlReader.Parse(template);

The problem is that when i try to run this I get the exception saying that the resource "BondListKey" cannot be found. Can anyone explain why?

Please let me know if you need anymore information.

In response to Johns comments :

I have a tab item and I want to be able to display different controls within that tab based on a user selection somewhere else on the form. As an example if the user selected a car I would like to be able to change the control template to include a textbox for engine size, fuel type etc, if the user selected an orange I would like a control template that included variety and sweetness. I suspect I could get this functionality by drawing all possible controls on the tab, then altering the visible/enabled state of the relvant controls based on a datatrigger, but this would potentially involve a LOT of filtered controls ( as there may be many user selection types ). What I ideally want to be able to do is have the desired control template supplied as a string, parsed and assigned to the template of the control, thus modifying its contents at runtime.

Please let me know if that didnt make sense or you need anythign clarifying :)

user589195
  • 4,180
  • 13
  • 53
  • 81

1 Answers1

2

StaticResource is a static lookup that is executed once at load time. If the target resource is not found at that time, you get an error, which is you're seeing now. Because you're loading the template in the context of the XamlReader the resources in your XAML aren't available. In most cases the fix is to use DynamicResource instead to provide a default value that gets updated when the resource becomes available, but Binding Source is not a DependencyProperty and so can't use Dynamic.

Rather than using a XamlReader, you can just declare your XAML in XAML and take advantage of the context that's available there:

<ContentControl x:Name="ccMaterial">
    <ContentControl.Resources>
        <x:Array x:Key="BondListKey" Type="sys:Int32"
             xmlns:sys="clr-namespace:System;assembly=mscorlib" />
        <ControlTemplate x:Key="MyTemplate">
            <ComboBox Grid.Column="1" Grid.Row="0" ItemsSource="{Binding Source={StaticResource BondListKey}}"  />
        </ControlTemplate>
    </ContentControl.Resources>
</ContentControl>

You can then still do the loading from code with:

ccMaterial.Template = ccMaterial.FindResource("MyTemplate") as ControlTemplate;
John Bowen
  • 24,213
  • 4
  • 58
  • 56
  • Thanks John I will give this a try. My only concern with your answer is that that the reason I am loading the template using the xaml reader is that I want to dynamically change the control template at runtime. Will using the method above not give the same error if I try to modify the control template at runtime containing a ref to a xaml resource? – user589195 Jan 29 '13 at 08:24
  • So if I create a control template like this I have no way of accessing resources and controls defined in my xaml? – user589195 Jan 29 '13 at 10:21
  • Could you add some more detail about what end result you're trying to achieve? When you say "dynamically change the control template" are you trying to change to a different template or modify the assigned instance? What didn't work? Declaring the template in XAML gives you access to anything within scope so I don't know what you mean by your last comment. There are numerous mechanisms for changing the runtime template behavior - Binding, Trigger, VisualState, template selectors... but without knowing what you're trying to do I can't recommend anything. – John Bowen Jan 29 '13 at 13:21