views:

1808

answers:

2

I've created a UserControl which is essentially a button. It's got an Image and a Label on it and I've created two properties to set the Image's source and the Label's text like so:

     public ImageSource Icon
 {
  get { return (ImageSource)this.GetValue(IconProperty); }
  set { this.SetValue(IconProperty, value); icon.Source = value; }
 }
 public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(ImageSource), typeof(NavigationButton));

 public string Text
 {
  get { return (string)this.GetValue(TextProperty); }
  set { this.SetValue(TextProperty, value); label.Content = value; }
 }

 public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(NavigationButton));

However, when I've added the control to my Page, the controls wont respond to any properties I set in XAML, e.g. <controls:MusicButton Icon="/SuCo;component/Resources/settings.png/> does nothing.

What am I doing wrong?

A: 

Have you tried setting the text property as well? The source of an image may just be wrong. Text is much more straight forward.

Also, in your example, you missed a quotation mark. So if it's copied from your real code, you may want to check that.

Barring those minor admittedly unlikely causes for your problem, I'd suggest setting the properties in code to check whether that has any effect. If it has, then you should really check your XAML.

Since you haven't posted the rest of your code, I can't really tell if you have problems somewhere else that might affect the control.

And yes, I know I'm not very helpful, but I've been working with WPF for only a little while. Hope it helps anyway.

SirDemon
+4  A: 

CLR properties that wrap dependency properties should never have any logic other than calling GetValue and SetValue. That is because they may not even be called. For example, the XAML compiler will optimize by calling GetValue/SetValue directly rather than using your CLR property.

If you need to execute some logic when a dependency property is changed, use metadata:

public ImageSource Icon
{
    get { return (ImageSource)this.GetValue(IconProperty); }
    set { this.SetValue(IconProperty, value); }
}

public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(ImageSource), typeof(NavigationButton), new FrameworkPropertyMetadata(OnIconChanged));

private static void OnIconChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
    //do whatever you want here - the first parameter is your DependencyObject
}

EDIT

In my first answer, I assumed your control's XAML (be it from a template or directly in a UserControl) is correctly hooked up to the properties. You haven't showed us that XAML, so it was perhaps an incorrect assumption. I'd expect to see something like:

<StackPanel>
    <Image Source="{Binding Icon}"/>
    <TextBlock Text="{Binding Text}"/>
</StackPanel>

And - importantly - your DataContext must be set to the control itself. You can do this in various different ways, but here is a very simple example of setting it from the code behind:

public YourControl()
{
    InitializeComponent();
    //bindings without an explicit source will look at their DataContext, which is this control
    DataContext = this;
}

HTH, Kent

Kent Boogaart
I added 'dependencyObject.SetValue(Image.SourceProperty, e.NewValue);' into the OnIconChanged void and it still seems to do nothing at all, in design- nor run-time. Even clearing the default Source value in the XAML doesn't fix it. Any further words of advice ? :P
Eric Smith
Does my edit help? If not, can you post all your code and XAML?
Kent Boogaart