Выделение SelectionChanged перед OnApplyTemplate в пользовательском элементе управления wpf - PullRequest
0 голосов
/ 20 сентября 2019

Я работаю над пользовательским элементом управления под названием select 2, вдохновленным WPF Auto Complete .Проблема в том, что мой OnSelectionChanged (связанный со свойством зависимости, называемым SelectedItem) вызывается перед OnApplyTemplate (все элементы управления инициализируются для пользовательского элемента управления) .Из-за чего в режиме обновления Элемент не выбирается, так как OnApplyTemplate был

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

    }

}

Так я его называю в моем XAML

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

Вот моя модель Свойство

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

ПЕРВОЕ ОБНОВЛЕНИЕ

Это происходит только в двух сценариях

1) Окно, котороесоздается во время выполнения.

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

2) Когда используется ContentControl.

Xaml:

<ContentControl x:Name="updateControl"/>

Code Behind

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

Обновление полки является пользовательским элементом управления.Просто для простоты я закодировал конструктор UpdateShelf следующим образом:

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

ВТОРОЕ ОБНОВЛЕНИЕ

Если я удаляю Datacontext из Конструктора в 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;
}

1 Ответ

1 голос
/ 20 сентября 2019

Создайте метод Initialize(), который выполняет операции инициализации, необходимые для того, чтобы элемент управления выполнялся как предполагалось (например, вызовите обратный вызов отсюда).Вызовите этот метод из обработчика событий OnApplyTemplate override или FrameworkElement.Loaded:

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();
  }
}
...