0
votes

I'm learning WPF and, coming from Flex and AS, it seems overly complicated at times. Opinions aside, my problem is the following.

I've created a custom control, ToolBarButton which is basically an image button that is destined to be included in a custom toolbar. I've added some properties to this control and I'd like to be able to set them from the XAML. Though the property appears in AutoCompletion on the XAML side, the Set method is never fired and the property stays null. So here's the ToolBarButton Code Behind :

    public static readonly DependencyProperty ImgSrcProperty = DependencyProperty.RegisterAttached("ImgSource", typeof(string), typeof(ToolBarButton));

    public static readonly DependencyProperty OnClickProperty = DependencyProperty.Register("OnClick", typeof(RoutedEventHandler), typeof(ToolBarButton));

    public ToolBarButton(RoutedEventHandler OnClick, string imgSrc, Map map = null, string ConfigFile = null) :
        base(ConfigFile, map)
    {
        if (OnClick != null) SetValue(OnClickProperty, OnClick);

        if (imgSrc != null) SetValue(ImgSrcProperty, imgSrc);

        this.AddChild(CreateButton());

        InitializeComponent();
    }

    public ToolBarButton() : this(null, null) { }

    private Button CreateButton()
    {
        BitmapImage icon = new BitmapImage();
        icon.BeginInit();
        icon.UriSource = new Uri(ImgSource, UriKind.Relative);
        icon.EndInit();

        Image img = new Image();
        img.Stretch = Stretch.Fill;
        img.Source = icon;

        Button BtnToAdd = new Button();
        BtnToAdd.Width = 35;
        BtnToAdd.Height = 35;
        BtnToAdd.Content = img;
        BtnToAdd.Background = new ImageBrush(icon);

        BtnToAdd.Click += OnClick;

        return BtnToAdd;
    }


    public string ImgSource
    {
        get { return (string)GetValue(ImgSrcProperty); }
        set { SetValue(ImgSrcProperty, value); }
    }

    public RoutedEventHandler OnClick
    {
        get { return (RoutedEventHandler)GetValue(OnClickProperty); }
        set { SetValue(OnClickProperty, value); }
    }

You'll notice two constructors, one to create the control at runtime, the other to create it from XAML.

And here's the XAML code that uses the custom control but doesn't fire the set method :

<BaseControls:ToolBar 
         x:Class="Basic_Mapping.Widgets.NavigationToolBar"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:BaseControls="clr-namespace:Basic_Mapping.Base_Controls"
         mc:Ignorable="d" >

<BaseControls:ToolBarButton Width="35" Height="35" ImgSource="Assets/i_zoomin.png"  ConfigFileName="ZoomIn.xml" />

Any help would be appreciated!

Ggilmann

EDIT :

Here's the Base Class used for the ToolBarButton, it also has the same problem with it's properties.

public partial class ConfigurableUserControl : UserControl
{
    private XmlDocument configXML;

    public static readonly DependencyProperty XmlProperty = DependencyProperty.Register("ConfigFileName", typeof(string), typeof(ConfigurableUserControl));

    public static readonly DependencyProperty MapProperty = DependencyProperty.Register("Map", typeof(Map), typeof(ConfigurableUserControl));

    public ConfigurableUserControl(string configFile, Map map)
    {
        if (configFile != null) SetValue(XmlProperty, configFile);

        if (map != null) SetValue(MapProperty, map);

        string file = (string)GetValue(XmlProperty);

        if (file != null)
        {
            configXML = new XmlDocument();

            string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\..\\Config\\" + configFile);

            if (File.Exists(path)) configXML.Load(path);
        }
    }

    public ConfigurableUserControl() : this(null, null) { }

    public string ConfigFileName
    {
        //get { return (string)GetValue(XmlProperty); }
        set { SetValue(XmlProperty, value); }
    }

    public Map Map
    {
        get { return (Map)GetValue(MapProperty); }
        set { SetValue(MapProperty, value); }
    }

    public XmlDocument ConfigXML
    {
        get { return configXML; }
    }
}
2
Your ImgSrcProperty is an attached property, which it should not be. And could you please list the base-class this derives from? You could add a OnPropertyChanged event to see if that get's fired (it should) as the getter and setter for DependecyProperties do not always fire with certain debug/compile-settings. - Kolky
I forgot to say that I also tried with basic get/set properties on a public variable but it did not help. I'll edit the original post to show the base class - Ggilmann

2 Answers

0
votes

My guess is that this problem, and your problems with the base class, are due to the fact that you're not implementing INotifyPropertyChanged and making the appropriate calls.

0
votes

Try putting InitializeComponent(); at the beginning of the constructor as opposed to at the end where it currently is.