Question

My Custom UserControl's dependency property will bind correctly if the value is statically defined in the XAML calling it, like this:

ItemTypeIdCode="addresses"

but not if the value is bound dynamically itself:

ItemTypeIdCode="{Binding ItemTypeIdCode}"

What do I have to do to my custom UserControl so that it's dependency property reacts to the value that is bound itself in another control?

Here is my code:

XAML:

<Window x:Class="TestDepenProp.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="clr-namespace:TestDepenProp.Controls"
    Title="Window1" Height="300" Width="300">
    <StackPanel 
        HorizontalAlignment="Left"
        Margin="10">
        <controls:DropDown 
            ItemTypeIdCode="{Binding ItemTypeIdCode}"  
            SelectedValue="672"
            Width="150"
            Margin="0 0 0 5"/>
        <TextBlock Text="{Binding ItemTypeIdCode}"/>
    </StackPanel>
</Window>

Code-Behind:

using System.Windows;
using System.ComponentModel;

namespace TestDepenProp
{
    public partial class Window1 : Window, INotifyPropertyChanged
    {
        #region ViewModelProperty: ItemTypeIdCode
        private string _itemTypeIdCode;
        public string ItemTypeIdCode
        {
            get
            {
                return _itemTypeIdCode;
            }

            set
            {
                _itemTypeIdCode = value;
                OnPropertyChanged("ItemTypeIdCode");
            }
        }
        #endregion

        public Window1()
        {
            InitializeComponent();
            DataContext = this;

            ItemTypeIdCode = "addresses";
        }
        #region INotifiedProperty Block
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}

DropDown.xaml:

<UserControl x:Class="TestDepenProp.Controls.DropDown"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
        <ComboBox SelectedValuePath="Key"
                  DisplayMemberPath="Value"
                  SelectedValue="{Binding SelectedValue}"
                  Margin="0 0 0 10"
                  ItemsSource="{Binding DropDownValues}" />
    </StackPanel>
</UserControl>

DropDown.xaml.cs:

using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Collections.Generic;

namespace TestDepenProp.Controls
{
    public partial class DropDown : UserControl, INotifyPropertyChanged
    {

        public static readonly DependencyProperty ItemTypeIdCodeProperty = DependencyProperty.Register("ItemTypeIdCode", typeof(string), typeof(DropDown));

        public string ItemTypeIdCode
        {
            get { return (string)GetValue(ItemTypeIdCodeProperty); }
            set { SetValue(ItemTypeIdCodeProperty, value); }
        }

        #region ViewModelProperty: DropDownValues
        private ObservableCollection<KeyValuePair<string, string>> _dropDownValues = new ObservableCollection<KeyValuePair<string, string>>();
        public ObservableCollection<KeyValuePair<string, string>> DropDownValues
        {
            get
            {
                return _dropDownValues;
            }

            set
            {
                _dropDownValues = value;
                OnPropertyChanged("DropDownValues");
            }
        }
        #endregion

        #region ViewModelProperty: SelectedValue
        private string _selectedValue;
        public string SelectedValue
        {
            get
            {
                return _selectedValue;
            }

            set
            {
                _selectedValue = value;
                OnPropertyChanged("SelectedValue");
            }
        }
        #endregion

        public DropDown()
        {
            InitializeComponent();
            DataContext = this;

            Loaded += new RoutedEventHandler(DropDown_Loaded);
        }

        void DropDown_Loaded(object sender, RoutedEventArgs e)
        {
            GetDropDownValues();
        }

        void GetDropDownValues()
        {
            switch (ItemTypeIdCode)
            {
                case "addresses":
                    DropDownValues.Add(new KeyValuePair<string, string>("111", "762 Main St."));
                    DropDownValues.Add(new KeyValuePair<string, string>("222", "7384 First Ave."));
                    DropDownValues.Add(new KeyValuePair<string, string>("333", "8728 Second St."));
                    break;
                case "customers":
                    DropDownValues.Add(new KeyValuePair<string, string>("672", "Jim Smith"));
                    DropDownValues.Add(new KeyValuePair<string, string>("281", "James Anders"));
                    DropDownValues.Add(new KeyValuePair<string, string>("321", "Angie Wonderson"));
                    DropDownValues.Add(new KeyValuePair<string, string>("221", "Hal Cloud"));
                    DropDownValues.Add(new KeyValuePair<string, string>("123", "Hugh Brandley"));
                    break;
                default:
                    break;
            }
        }


        #region INotifiedProperty Block
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion


    }
}
Was it helpful?

Solution

I think you need to add PropertyChangedCallback to your ItemTypeIdCodeProperty dependency property. In this callback you are to call GetDropDownValues().

OTHER TIPS

My guess is the Combobox does not show any entries. This is indeed a bit tricky. A control works in 2 totally Independent "adress spaces". The first is it's own data like all dependency properties. The second "adresse space" is the data context it inherits from it's parent. If nothing special is done all bindings work on the data context. In case you want to refer to the control's data you need to add an explicit "reference" to yourself:

<UserControl x:Class="TestDepenProp.Controls.DropDown"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="self">
<StackPanel>
    <ComboBox SelectedValuePath="Key"
              DisplayMemberPath="Value"
              SelectedValue="{Binding SelectedValue, ElementName=self}"
              Margin="0 0 0 10"
              ItemsSource="{Binding DropDownValues, ElementName=self}" />
</StackPanel>

OnPropertyChanged isn't needed, that's already handled by the dependency property logic.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top