Safi Mustafa
Safi Mustafa

Reputation: 517

SelectionChanged Called before OnApplyTemplate in wpf Custom Control

I am working on a custom control called select 2 inspired by WPF Auto Complete. The problem is that my OnSelectionChanged (binded with a Dependecy Property called SelectedItem) is called before OnApplyTemplate (all controls are initialized for the custom control). Because of which in updation mode the Item is not gettiing selected as OnApplyTemplate was

using Helpers.CustomControls.AutoComplete;
using Helpers.CustomControls.AutoComplete.CustomPopupControl;
using Helpers.CustomControls.AutoComplete.Interfaces;
using System;
using System.Collections;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace Helpers.CustomControls.AutoComplete
{
    [TemplatePart(Name = PartGridContainer, Type = typeof(Grid))]
    [TemplatePart(Name = PartEditor, Type = typeof(TextBox))]
    [TemplatePart(Name = PartSelect2, Type = typeof(TextBox))]
    [TemplatePart(Name = PartSuggestionBoxContainer, Type = typeof(StackPanel))]
    [TemplatePart(Name = PartPopup, Type = typeof(Popup))]
    [TemplatePart(Name = PartSelector, Type = typeof(Selector))]
    [TemplatePart(Name = Select2DownArrow, Type = typeof(Path))]
    [TemplatePart(Name = Select2UpArrow, Type = typeof(Path))]
    public class AutoCompleteTextBox : Control
    {

        #region "Fields"
        public const string PartGridContainer = "PART_GridContainer";
        public const string PartEditor = "PART_Editor";
        public const string PartPopup = "PART_Popup";
        public const string PartSelect2 = "PART_Select2";
        public const string PartSuggestionBoxContainer = "PART_SuggestionBoxContainer";
        public const string PartSelector = "PART_Selector";
        public const string Select2UpArrow = "Select2UpArrow";
        public const string Select2DownArrow = "Select2DownArrow";
        public static readonly DependencyProperty DelayProperty = DependencyProperty.Register("Delay", typeof(int), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(200));
        public static readonly DependencyProperty DisplayMemberProperty = DependencyProperty.Register("DisplayMember", typeof(string), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(string.Empty));
        public static readonly DependencyProperty IconPlacementProperty = DependencyProperty.Register("IconPlacement", typeof(IconPlacement), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(IconPlacement.Left));
        public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(object), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null));
        public static readonly DependencyProperty IconVisibilityProperty = DependencyProperty.Register("IconVisibility", typeof(Visibility), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(Visibility.Visible));
        public static readonly DependencyProperty IsSelect2Property = DependencyProperty.Register("IsSelect2", typeof(bool), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(false));
        public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register("IsDropDownOpen", typeof(bool), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(false));
        public static readonly DependencyProperty IsLoadingProperty = DependencyProperty.Register("IsLoading", typeof(bool), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(false));
        public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(false));
        public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null));
        public static readonly DependencyProperty ItemTemplateSelectorProperty = DependencyProperty.Register("ItemTemplateSelector", typeof(DataTemplateSelector), typeof(AutoCompleteTextBox));
        public static readonly DependencyProperty LoadingContentProperty = DependencyProperty.Register("LoadingContent", typeof(object), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null));
        public static readonly DependencyProperty ProviderProperty = DependencyProperty.Register("Provider", typeof(ISuggestionProvider), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null));
        public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null, OnSelectedItemChanged));
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(string.Empty));
        public static readonly DependencyProperty MaxLengthProperty = DependencyProperty.Register("MaxLength", typeof(int), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(0));
        public static readonly DependencyProperty CharacterCasingProperty = DependencyProperty.Register("CharacterCasing", typeof(CharacterCasing), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(CharacterCasing.Normal));
        public static readonly DependencyProperty MaxPopUpHeightProperty = DependencyProperty.Register("MaxPopUpHeight", typeof(int), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(600));

        public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(string), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(string.Empty));

        public static readonly DependencyProperty SuggestionBackgroundProperty = DependencyProperty.Register("SuggestionBackground", typeof(Brush), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(Brushes.White));
        private bool _isUpdatingText;
        private bool _selectionCancelled;

        private SuggestionsAdapter _suggestionsAdapter;


        #endregion

        #region "Constructors"

        static AutoCompleteTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(typeof(AutoCompleteTextBox)));

        }
        #endregion

        #region "Properties"


        public int MaxPopupHeight
        {
            get => (int)GetValue(MaxPopUpHeightProperty);
            set => SetValue(MaxPopUpHeightProperty, value);
        }


        public BindingEvaluator BindingEvaluator { get; set; }

        public CharacterCasing CharacterCasing
        {
            get => (CharacterCasing)GetValue(CharacterCasingProperty);
            set => SetValue(CharacterCasingProperty, value);
        }

        public int MaxLength
        {
            get => (int)GetValue(MaxLengthProperty);
            set => SetValue(MaxLengthProperty, value);
        }

        public int Delay
        {
            get => (int)GetValue(DelayProperty);

            set => SetValue(DelayProperty, value);
        }

        public string DisplayMember
        {
            get => (string)GetValue(DisplayMemberProperty);

            set => SetValue(DisplayMemberProperty, value);
        }

        private TextBox Select2 { get; set; }
        private TextBox Editor { get; set; }

        public DispatcherTimer FetchTimer { get; set; }

        public string Filter { get; set; }

        public object Icon
        {
            get => GetValue(IconProperty);

            set => SetValue(IconProperty, value);
        }

        public IconPlacement IconPlacement
        {
            get => (IconPlacement)GetValue(IconPlacementProperty);

            set => SetValue(IconPlacementProperty, value);
        }

        public Visibility IconVisibility
        {
            get => (Visibility)GetValue(IconVisibilityProperty);

            set => SetValue(IconVisibilityProperty, value);
        }
        public bool IsSelect2
        {
            get => (bool)GetValue(IsSelect2Property);

            set => SetValue(IsSelect2Property, value);
        }

        public bool IsDropDownOpen
        {
            get => (bool)GetValue(IsDropDownOpenProperty);

            set => SetValue(IsDropDownOpenProperty, value);
        }

        public bool IsLoading
        {
            get => (bool)GetValue(IsLoadingProperty);

            set => SetValue(IsLoadingProperty, value);
        }

        public bool IsReadOnly
        {
            get => (bool)GetValue(IsReadOnlyProperty);

            set => SetValue(IsReadOnlyProperty, value);
        }

        public Selector ItemsSelector { get; set; }

        public DataTemplate ItemTemplate
        {
            get => (DataTemplate)GetValue(ItemTemplateProperty);

            set => SetValue(ItemTemplateProperty, value);
        }

        public DataTemplateSelector ItemTemplateSelector
        {
            get => ((DataTemplateSelector)(GetValue(ItemTemplateSelectorProperty)));
            set => SetValue(ItemTemplateSelectorProperty, value);
        }

        public object LoadingContent
        {
            get => GetValue(LoadingContentProperty);

            set => SetValue(LoadingContentProperty, value);
        }
        private Grid GridContainer { get; set; }
        private Popup Select2Popup { get; set; }
        private StackPanel SuggestionBoxContainer { get; set; }
        private Popup Popup { get; set; }



        public ISuggestionProvider Provider
        {
            get => (ISuggestionProvider)GetValue(ProviderProperty);

            set => SetValue(ProviderProperty, value);
        }

        public object SelectedItem
        {
            get => GetValue(SelectedItemProperty);

            set => SetValue(SelectedItemProperty, value);
        }

        public SelectionAdapter SelectionAdapter { get; set; }

        public string Text
        {
            get => (string)GetValue(TextProperty);

            set => SetValue(TextProperty, value);
        }

        public string Watermark
        {
            get => (string)GetValue(WatermarkProperty);

            set => SetValue(WatermarkProperty, value);
        }
        public Brush SuggestionBackground
        {
            get => (Brush)GetValue(SuggestionBackgroundProperty);

            set => SetValue(SuggestionBackgroundProperty, value);
        }

        #endregion

        #region "Methods"

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            GridContainer = Template.FindName(PartGridContainer, this) as Grid;
            Select2 = Template.FindName(PartSelect2, this) as TextBox;
            Editor = Template.FindName(PartEditor, this) as TextBox;
            Popup = Template.FindName(PartPopup, this) as Popup;
            ItemsSelector = Template.FindName(PartSelector, this) as Selector;

            if (IsSelect2)
            {
                SuggestionBoxContainer = Template.FindName(PartSuggestionBoxContainer, this) as StackPanel;
                if (GridContainer != null)
                {
                    GridContainer.Children.Remove(SuggestionBoxContainer);
                    Select2Popup = InitializeSelect2Popup();
                    Select2Popup.Child = SuggestionBoxContainer;
                    GridContainer.Children.Add(Select2Popup);
                    Grid.SetRow(Select2Popup, 1);
                }
                if (Select2 != null)
                {
                    Select2.PreviewKeyDown += OnSelect2PreviewKeyDown;
                    Select2.PreviewMouseDown += OnSelect2PreviewMouseDown;

                }
            }
            else
            {
                if (Select2 != null)
                {
                    Select2.Visibility = Visibility.Collapsed;
                }
            }



            BindingEvaluator = new BindingEvaluator(new Binding(DisplayMember));

            if (Editor != null)
            {
                Editor.TextChanged += OnEditorTextChanged;
                Editor.PreviewKeyDown += OnEditorKeyDown;
                Editor.LostFocus += OnEditorLostFocus;

                if (SelectedItem != null)
                {
                    _isUpdatingText = true;
                    Editor.Text = BindingEvaluator.Evaluate(SelectedItem);
                    _isUpdatingText = false;
                }

            }

            if (Popup != null)
            {
                Popup.StaysOpen = false;
                Popup.Opened += OnPopupOpened;
                Popup.Closed += OnPopupClosed;
            }

            if (ItemsSelector != null)
            {
                SelectionAdapter = new SelectionAdapter(ItemsSelector);
                SelectionAdapter.Commit += OnSelectionAdapterCommit;
                SelectionAdapter.Cancel += OnSelectionAdapterCancel;
                SelectionAdapter.SelectionChanged += OnSelectionAdapterSelectionChanged;
                ItemsSelector.PreviewMouseDown += ItemsSelector_PreviewMouseDown;
            }
        }

        public static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
       {
            AutoCompleteTextBox act = null;
            act = d as AutoCompleteTextBox;
            if (act != null)
            {
                if (act.Editor != null & !act._isUpdatingText)
                {
                    act._isUpdatingText = true;
                    act.Editor.Text = act.BindingEvaluator.Evaluate(e.NewValue);
                    if (act.Select2 != null)
                    {
                        act.Select2.Text = act.BindingEvaluator.Evaluate(e.NewValue);
                    }
                    act._isUpdatingText = false;
                }
            }
        }

        private void ScrollToSelectedItem()
        {
            if (ItemsSelector is ListBox listBox && listBox.SelectedItem != null)
                listBox.ScrollIntoView(listBox.SelectedItem);
        }



        private void ItemsSelector_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            if ((e.OriginalSource as FrameworkElement)?.DataContext == null)
                return;
            if (!ItemsSelector.Items.Contains(((FrameworkElement)e.OriginalSource)?.DataContext))
                return;
            ItemsSelector.SelectedItem = ((FrameworkElement)e.OriginalSource)?.DataContext;
            OnSelectionAdapterCommit();
        }

        private string GetDisplayText(object dataItem)
        {
            if (BindingEvaluator == null)
            {
                BindingEvaluator = new BindingEvaluator(new Binding(DisplayMember));
            }
            if (dataItem == null)
            {
                return string.Empty;
            }
            if (string.IsNullOrEmpty(DisplayMember))
            {
                return dataItem.ToString();
            }
            return BindingEvaluator.Evaluate(dataItem);
        }

        private void OnEditorKeyDown(object sender, KeyEventArgs e)
        {
            if (IsSelect2 && (e.Key == Key.Escape || (IsDropDownOpen == false && e.Key == Key.Enter)))
            {
                CloseSelect2Suggestions();
                e.Handled = true;
                return;
            }
            if (SelectionAdapter != null)
            {
                if (IsDropDownOpen)
                    SelectionAdapter.HandleKeyDown(e);
                else
                    IsDropDownOpen = e.Key == Key.Down || e.Key == Key.Up;
            }
        }

        private void OnEditorLostFocus(object sender, RoutedEventArgs e)
        {
            if (!IsKeyboardFocusWithin)
            {
                IsDropDownOpen = false;
            }
        }

        private void OnEditorTextChanged(object sender, TextChangedEventArgs e)
        {
            if (_isUpdatingText)
                return;
            if (FetchTimer == null)
            {
                FetchTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(Delay) };
                FetchTimer.Tick += OnFetchTimerTick;
            }
            FetchTimer.IsEnabled = false;
            FetchTimer.Stop();
            if (IsSelect2 == false)
            {
                SetSelectedItem(null);
            }
            if (Editor.Text.Length > 0)
            {
                FetchTimer.IsEnabled = true;
                FetchTimer.Start();
            }
            else
            {
                IsDropDownOpen = false;
            }
        }

        private void OnSelect2PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key != Key.Enter && e.Key != Key.Tab)
            {
                e.Handled = true;
                return;
            }
            if (e.Key == Key.Enter)
            {
                ToggleSelect2();
            }

        }
        private void OnSelect2PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            ToggleSelect2();
            e.Handled = true;
            return;
        }

        private void OnFetchTimerTick(object sender, EventArgs e)
        {
            FetchTimer.IsEnabled = false;
            FetchTimer.Stop();
            if (Provider != null && ItemsSelector != null)
            {
                Filter = Editor.Text;
                if (_suggestionsAdapter == null)
                {
                    _suggestionsAdapter = new SuggestionsAdapter(this);
                }
                _suggestionsAdapter.GetSuggestions(Filter);
            }
        }

        private void OnPopupClosed(object sender, EventArgs e)
        {
            if (!_selectionCancelled)
            {
                OnSelectionAdapterCommit();
            }
        }

        private void OnPopupOpened(object sender, EventArgs e)
        {
            _selectionCancelled = false;
            ItemsSelector.SelectedItem = SelectedItem;
        }

        private void OnSelectionAdapterCancel()
        {
            _isUpdatingText = true;
            Editor.Text = SelectedItem == null ? Filter : GetDisplayText(SelectedItem);
            Editor.SelectionStart = Editor.Text.Length;
            Editor.SelectionLength = 0;
            _isUpdatingText = false;
            IsDropDownOpen = false;
            _selectionCancelled = true;
        }

        private void OnSelectionAdapterCommit()
        {
            if (ItemsSelector.SelectedItem != null)
            {
                SelectedItem = ItemsSelector.SelectedItem;
                _isUpdatingText = true;
                Editor.Text = GetDisplayText(ItemsSelector.SelectedItem);
                if (IsSelect2 && Select2 != null)
                    Select2.Text = GetDisplayText(ItemsSelector.SelectedItem);
                SetSelectedItem(ItemsSelector.SelectedItem);
                _isUpdatingText = false;
                IsDropDownOpen = false;
                if (IsSelect2)
                    CloseSelect2Suggestions();
            }
        }

        private void OnSelectionAdapterSelectionChanged()
        {
            _isUpdatingText = true;
            Editor.Text = ItemsSelector.SelectedItem == null ? Filter : GetDisplayText(ItemsSelector.SelectedItem);
            Editor.SelectionStart = Editor.Text.Length;
            Editor.SelectionLength = 0;
            ScrollToSelectedItem();
            _isUpdatingText = false;
        }

        private void SetSelectedItem(object item)
        {
            _isUpdatingText = true;
            SelectedItem = item;
            _isUpdatingText = false;
        }
        #endregion

        #region[Supportive Functions]
        private void OpenSelect2Suggestions()
        {
            if (Select2Popup.IsOpen == false)
            {
                if (Select2Popup != null)
                    Select2Popup.IsOpen = true;
                Editor?.Focus();
                IsDropDownOpen = false;

                var upArrow = (Template.FindName(Select2UpArrow, this) as Path);
                var downArrow = (Template.FindName(Select2DownArrow, this) as Path);
                if (upArrow != null && downArrow != null)
                {
                    upArrow.Visibility = Visibility.Visible;
                    downArrow.Visibility = Visibility.Collapsed;
                }
            }
        }
        private void CloseSelect2Suggestions()
        {
            if (Select2Popup.IsOpen == true)
            {
                if (Select2Popup != null)
                    Select2Popup.IsOpen = false;
                Select2?.Focus();
                IsDropDownOpen = false;
            }
        }
        private void ToggleSelect2()
        {
            if (Select2Popup.IsOpen)
                CloseSelect2Suggestions();
            else
                OpenSelect2Suggestions();
        }
        private PopupNonTopmost InitializeSelect2Popup()
        {
            PopupNonTopmost select2Popup = new PopupNonTopmost();
            select2Popup.HorizontalAlignment = HorizontalAlignment.Stretch;
            select2Popup.Width = 300;
            select2Popup.IsOpen = false;
            select2Popup.PlacementTarget = Select2;
            select2Popup.Placement = PlacementMode.Bottom;
            select2Popup.AllowsTransparency = true;
            select2Popup.PopupAnimation = PopupAnimation.Slide;
            select2Popup.Focusable = false;

            Binding widthBinding = new Binding("ActualWidth") { ElementName = PartSelect2 };
            select2Popup.SetBinding(FrameworkElement.WidthProperty, widthBinding);
            return select2Popup;
        }
        #endregion

        #region "Nested Types"

        private class SuggestionsAdapter
        {

            #region "Fields"

            private readonly AutoCompleteTextBox _actb;

            private string _filter;
            #endregion

            #region "Constructors"

            public SuggestionsAdapter(AutoCompleteTextBox actb)
            {
                _actb = actb;
            }

            #endregion

            #region "Methods"

            public void GetSuggestions(string searchText)
            {
                _filter = searchText;
                _actb.IsLoading = true;
                _actb.IsDropDownOpen = true;
                _actb.ItemsSelector.ItemsSource = null;
                ParameterizedThreadStart thInfo = GetSuggestionsAsync;
                Thread th = new Thread(thInfo);
                th.Start(new object[] {
                searchText,
                _actb.Provider
            });
            }

            private void DisplaySuggestions(IEnumerable suggestions, string filter)
            {
                if (_filter != filter)
                {
                    return;
                }
                if (_actb.IsDropDownOpen)
                {
                    _actb.IsLoading = false;
                    _actb.ItemsSelector.ItemsSource = suggestions;
                    var interfaceType = typeof(IAutoCompleteItem);
                    _actb.ItemsSelector.DisplayMemberPath = interfaceType.GetProperties().FirstOrDefault().Name;
                    _actb.IsDropDownOpen = _actb.ItemsSelector.HasItems;
                }

            }

            private void GetSuggestionsAsync(object param)
            {
                if (param is object[] args)
                {
                    string searchText = Convert.ToString(args[0]);
                    if (args[1] is ISuggestionProvider provider)
                    {
                        IEnumerable list = provider.GetSuggestions(searchText);
                        _actb.Dispatcher.BeginInvoke(new Action<IEnumerable, string>(DisplaySuggestions), DispatcherPriority.Background, list, searchText);
                    }
                }
            }

            #endregion

        }

        #endregion

    }

}

This is how I am calling it in my XAML

<ac:AutoCompleteTextBox x:Name="searchFloors" Tag="Floor" IsSelect2="True" Style="{StaticResource Select2Style}" DisplayMember="SearchText" SelectedItem="{Binding Floor,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />

Here is my model Property

public FloorViewModel FloorModel
{
    get { return floorModel; }
    set
    {
        floorModel = value;
        // Call OnPropertyChanged whenever the property is updated
        OnPropertyChanged("FloorModel");
    }
}

FIRST UPDATE

This only happens in two scenarios

1) A Window that is created on runtime.

Window window = new Window();
window.Content = UpdateShelf(MainWindow, Shelf, GridList.ResultList)

2) When ContentControl is used.

Xaml:

<ContentControl x:Name="updateControl"/>

Code Behind

 var updateUC = new UpdateShelf(MainWindow, Shelf, GridList.ResultList);
 ShowUpdateUC();
 updateControl.Content = updateUC;
 updateUC.GoBack += UpdateGoBack_Event;

Update Shelf is a user Control. Just for the sake of simplicity I have coded UpdateShelf Constructor Like this:

public UpdateShelf(MainDashboard MainWindow, ShelfViewModel shelf, ObservableCollection<ShelfViewModel> gridList)
{
        InitializeComponent();
        shelfViewModel = shelf ?? new ShelfViewModel();
        shelfViewModel.FloorModel = new FloorViewModel(){Name="Floor One"};
        DataContext = shelfViewModel;
}

SECOND UPDATE

If i remove Datacontext from Constructor to Loaded Function. It works as expected, but why is this happening and is it better to set datacontext in loaded function?

public UpdateShelf(MainDashboard MainWindow, ShelfViewModel shelf, ObservableCollection<ShelfViewModel> gridList)
{
        InitializeComponent();
        shelfViewModel = shelf ?? new ShelfViewModel();
        shelfViewModel.FloorModel = new FloorViewModel(){Name="Floor One"};
         #region[Events Registrations]
         Loaded += new RoutedEventHandler(UpdateShelfView_Loaded);
         Unloaded += new RoutedEventHandler(UpdateShelfView_UnLoaded);
         #endregion
}

void UpdateShelfView_Loaded(object sender, RoutedEventArgs e)
{
    DataContext = shelfViewModel;
}

Upvotes: 0

Views: 790

Answers (1)

BionicCode
BionicCode

Reputation: 29028

Create a Initialize() method that performs the initialization operations required for the control to perform as intended (e.g. invoke the callback from here). Call this method from your OnApplyTemplate override or FrameworkElement.Loaded event handler:

public class AutoCompleteTextBox : Control
{ 
    public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
    "SelectedItem",
    typeof(object),
    typeof(AutoCompleteTextBox),
    new FrameworkPropertyMetadata(null, OnSelectedItemChanged));

  public object SelectedItem { get => (object)GetValue(AutoCompleteTextBox.SelectedItemProperty); set => SetValue(AutoCompleteTextBox.SelectedItemProperty, value);  }

  private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
    ...
  }

  private void Initialize()
  {
    AutoCompleteTextBox.OnSelectedItemChanged(this, new DependencyPropertyChangedEventArgs(AutoCompleteTextBox.SelectedItemProperty, this.SelectedItem, this.SelectedItem));
  }    

  public AutoCompleteTextBox()
  {
    InitializeComponent(); 
    this.Loaded  += () => Initialize();
  }
}

Upvotes: 1

Related Questions