views:

540

answers:

2

Ok, I have a ResourceDictionary definition that I used for a WPF app below:

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

<Style x:Key="fieldsPanel" TargetType="{x:Type StackPanel}">
 <Style.Resources>
  <Style TargetType="{x:Type CheckBox}">
   <Setter Property="Margin" Value="8 2" />
  </Style>
  <Style TargetType="{x:Type TextBlock}">
   <Setter Property="Margin" Value="0 2" />
   <Setter Property="Width" Value="100" />
  </Style> 
 </Style.Resources>
</Style>

This exact block of XAML, when brought into my Silverlight app, shows 4 errors in the error pane (the first error appears 3 times, the second once)

  1. The tag 'Type' does not exist in XML namespace 'http://schemas.microsoft.com/winfx/2006/xaml'

  2. The property 'Resources' does not exist on the type 'Style' in the XML namespace 'http://schemas.microsoft.com/winfx/2006/xaml/presentation'

I can make all instances of the first error go away by replacing the "{x:Type TypeName}" text with "TypeName". But is this the correct way to fix this? Is this just another random and arbitrary difference between WPF and Silverlight?

But I can't figure out what I'm doing wrong in the second error. Can anyone give me some help (and the place you found the answer)?

EDIT:

If I knew how to Google "Style.Resources" (so that Google wouldn't ignore the dot) or if I knew the terminology for what that type of construct is called, I think could figure it out for myself.

EDIT:

It turns out that what I was trying to accomplish is probably best done with a UserControl. But apparently I need to learn a whole new set of rules for making UserControls in Silverlight.

In short, I want something like this:

<CheckBox Click="myClickHandler"  Name="myName"/><TextBlock Text="The label for the checkbox" />

...made into a UserControl which I can instantiate several times with different names and labels. All checkboxes will use the same click handler.

If anyone wants to whip up some quick UserControl code and post it, I'd appreciate it. If not (and I totally understand not wanting to do free work for someone else), I'll start Googling.

+2  A: 

At first sight it appears to be the correct way to fix the problem and it does appear to be "another random and arbitrary difference" between WPF and Silverlight. However, making that change doesn't actually produce code that works.

As Klay correctly points out in his latest edit, what he actually needs to do is produce a UserControl with the Dependency Properties for the variable parts (Text etc.).

Here's the ResourceDictonary page on MSDN which has more information on the format.

Don't forget the Silverlight is not really a sub-set of WPF. Microsoft had to completely rewrite the code that runs Silverlight apps so that the runtime is a small download.

EDIT

The XAML you need is:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyControls">
    >
    <Style TargetType="StackPanel">
        <Setter Property="Template">
            <Setter.Value>
                <Control Template TargetType="local:myPanel">
                    <CheckBox x:Name="myCheckBox"
                              Content="{TemplateBinding CheckBoxLabel}"
                              Margin="8,0,2,0" Width = "100"/>
                </Control>
            </Setter.Value>
         </Setter>    
    </Style>
</ResourceDictionary>

Then you'll need to create a cs file containing the code for your user control:

namespace MyControls
{
    public class myPanel : ContentControl
    {
        public myPanel()
        {
            DefaultStyleKey = typeof(myPanel);
        }
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        CheckBox checkbox = GetTemplateChild("myCheckBox") as CheckBox;
        checkbox.Click += CheckBoxClick;
    }

    void CheckBoxClick(object sender, RoutedEventArgs e)
    {
        CheckBox checkbox = sender as CheckBox;
        // Do this CheckBox specific stuff
    }

    public string CheckBoxLabel
    {
        get { return (string)GetValue(CheckBoxLabelProperty); }
        set { SetValue(CheckBoxLabelProperty, value); }
    }

    public static readonly DependencyProperty CheckBoxLabelProperty =
        DependencyProperty.Register("CheckBoxLabel", typeof(string),
                                    typeof(myPanel), null);
 }

Disclaimer - I've just put this together from a more complex user control so there's no guarantee that it'll work "out of the box". You'll probably need to tweak it a bit to get it working 100%.

ChrisF
Thanks for the swift reply. I'll accept this answer if you can tell me how I can restructure the Style.Resources bit to get rid of the second error.
Klay
Sorry I didn't notice your edit sooner. Thanks!
Klay
Oops. Accespted too soon. The error goes away in the edito, but it gives a runtime error: "Style does not support Style as content. [Line: 6 Position: 31]"
Klay
Now it *is* in the editor: "A value of type 'Style' cannot be added to a collection or dictionary of type 'SetterBaseCollection'."
Klay
ChrisF
+1  A: 

I'm not sure I would bother creating new control since no new functionality is required, at very worst case you might need to provide a whole new template for CheckBox if you really wanted to go to town on the way it looks. However I doubt you even need to touch the template in this case.

The Padding property ends up as the Margin property of the inner ContentPresenter of the default template. If you must have the label width exactly 100 pixels then you can set the Checkbox control width to 116 (the check box itself is 16 pixels).

Hence your desired visuals can be approached like this with:-

<CheckBox x:Name="myName" Content="The label for the checkbox"
  Margin="8 2 0 2" Padding="8 0 0 0" Width="116" />

One key difference with SL compared to WPF is you can't locally override the style for a Type. You need to bind the Style property of a control to a resource:-

<UserControl .... blah, blah>
   <UserControl.Resources>
       <Style x:Key="MyCheckBoxes" TargetType="CheckBox">
           <Setter Name="Margin" Value="8 2 0 2" />
           <Setter Name="Padding" Value="8 0 0 0" />
           <Setter Name="Width" Value="116" />
       </Style>
   </UserControl.Resources>
  <CheckBox x:Name="myName" Content="The label for the checkbox"
    Style="{StaticResource MyCheckBoxes}" />
AnthonyWJones