views:

313

answers:

2

I am trying to create an attached behavior that can be applied to a Silverlight ComboBox.

My behavior is this:

using System.Windows.Controls;
using System.Windows;
using System.Windows.Controls.Primitives;

namespace AttachedBehaviours
{
    public class ConfirmChangeBehaviour 
    {

        public static bool GetConfirmChange(Selector cmb)
        {
            return (bool)cmb.GetValue(ConfirmChangeProperty);
        }

        public static void SetConfirmChange(Selector cmb, bool value)
        {
            cmb.SetValue(ConfirmChangeProperty, value);
        }


        public static readonly DependencyProperty ConfirmChangeProperty =
            DependencyProperty.RegisterAttached("ConfirmChange", typeof(bool), typeof(Selector), new PropertyMetadata(true, ConfirmChangeChanged));
        public static void ConfirmChangeChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
        {
            Selector instance = d as Selector;

            if (args.NewValue is bool == false)
                return;

            if ((bool)args.NewValue)
                instance.SelectionChanged += OnSelectorSelectionChanged;
            else
                instance.SelectionChanged -= OnSelectorSelectionChanged;

        }

        static void OnSelectorSelectionChanged(object sender, RoutedEventArgs e)
        {
            Selector item = e.OriginalSource as Selector;

            MessageBox.Show("Unsaved changes. Are you sure you want to change teams?");    

        }

    }

}

This is used in XAML as this:

<UserControl x:Class="AttachedBehaviours.MainPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:this="clr-namespace:AttachedBehaviours"
             mc:Ignorable="d">
    <Grid x:Name="LayoutRoot">
        <StackPanel>
            <ComboBox ItemsSource="{Binding Teams}" 
                      this:ConfirmChangeBehaviour.ConfirmChange="true" >
            </ComboBox>
        </StackPanel>
    </Grid>
</UserControl>

I am getting an error:

Unknown attribute ConfirmChangeBehaviour.ConfirmChange on element ComboBox. [Line: 13 Position: 65]

Intellisense is picking up the behavior, why is this failing at runtime?

Thanks, Mark

EDIT: Register() changed to RegisterAttached(). Same error appears.

+1  A: 

You need to change this:

DependencyProperty.Register("ConfirmChange"...

to this:

DependencyProperty.RegisterAttached("ConfirmChange"...

Attached properties (including attached behaviours) must be registered using RegisterAttached rather than plain old Register.

itowlson
Thanks for the tip and quick answer +1. You are correct about the new registration, but the error message is still the same? Any further ideas?
Mark Cooper
+4  A: 

You've misregistered your attached property

public static readonly DependencyProperty ConfirmChangeProperty =
        DependencyProperty.RegisterAttached("ConfirmChange", typeof(bool), typeof(Selector), new PropertyMetadata(true, ConfirmChangeChanged));

Should be

public static readonly DependencyProperty ConfirmChangeProperty =
        DependencyProperty.RegisterAttached("ConfirmChange", typeof(bool), typeof(ConfirmChangeBehaviour), new PropertyMetadata(true, ConfirmChangeChanged));

May I advise you to move over to using the Blend Interactivity Behaviours. Writing XAML as opposed to using a tool never makes Designers happy.

Graeme Bradbury
As a tip, Visual Studio has a snippet (`propa`) which can help avoid these kinds of typos (though it still allows you to get the owner class wrong, sigh).
itowlson