Search code examples
c#windows-phone-7resourcedictionaryviewbox

using viewbox in ResourceDictionary file


i have ResourceFile1.xaml file its content

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Viewbox x:Key="Flash-On" >
    <Grid  Width="256" Height="256" Visibility="Visible">
        <Path Tag="Icon" Data="F1M376.251,632.755L385.665,632.755 381.302,646.07 394.618,646.07 389.11,660.302 393.01,660.302 381.531,672.93 377.398,660.763 381.073,660.763 383.829,652.268 369.825,652.268 376.251,632.755z" Stretch="Uniform" Fill="#FFFFFFFF" Width="176" Height="176" Margin="0,0,0,0" RenderTransformOrigin="0.5,0.5">
            <Path.RenderTransform>
                <TransformGroup>
                    <TransformGroup.Children>
                        <RotateTransform Angle="0" />
                        <ScaleTransform ScaleX="1" ScaleY="1" />
                    </TransformGroup.Children>
                </TransformGroup>
            </Path.RenderTransform>
        </Path>
    </Grid>
</Viewbox>


<Viewbox x:Key="Flash-Off">
            ....
</Viewbox>
</ResourceDictionary>

The code for PhoneAppplicationPage

    <phone:PhoneApplicationPage.Resources>

    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="ResourceFile1.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</phone:PhoneApplicationPage.Resources>

but this codes not working. Designer Error: InvalidOperationException: Element is already the child of another element. also <Button Content="{StaticResource Flash-On}"/> If I use a similar code Runtime Error: Failed to assign to property 'System.Windows.Controls.ContentControl.Content'. if viewbox use in Grid.Resources no problem works fine but i want to use with ResourceDictionary.how can i do?


Solution

  • Because everything inside a Silverlight resource dictionary must be shareable. In WPF, you can use the x:Shared attribute on objects inside a resource dictionary to force WPF to create a new instance for every resource retrieval. To avoid this in Silverlight you can create a DataTemplate:

    <DataTemplate x:Key="ButtonTemplate">
        <Viewbox>
    <!-- Here your content-->
        </Viewbox>
    </DataTemplate>
    
    <Button ContentTemplate="{StaticResource ButtonTemplate}"/>
    

    UPDATE 0

    I wrote an example that changes the template that depends on the value of the CheckBox.

    Converter to change a template:

    public class TemplateSelectorConverter : IValueConverter
    {
        public DataTemplate TrueTemplate { get; set; }
    
        public DataTemplate FalseTemplate { get; set; }
    
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (((bool) value))
                return TrueTemplate;
            return FalseTemplate;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
    

    Resources:

    <DataTemplate x:Key="FirstTemplate">
        <TextBox Text="FirstTemplate" />
    </DataTemplate>
    
    <DataTemplate x:Key="SecondTemplate">
        <TextBox Text="SecondTemplate" />
    </DataTemplate>
    
    <internal:TemplateSelectorConverter x:Key="TemplateSelector" TrueTemplate="{StaticResource FirstTemplate}"
                                        FalseTemplate="{StaticResource SecondTemplate}" />
    

    Xaml markup:

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="30" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
    
        <CheckBox Name="CheckBox"/>
        <Button Grid.Column="1"
                ContentTemplate="{Binding Path=IsChecked, ElementName=CheckBox, Converter={StaticResource TemplateSelector}}"
                VerticalAlignment="Top" />
    </Grid>
    

    I hope this helps.