Wpf实现TreeSelect

2021-01-01 15:30

阅读:696

标签:closed   on()   bottom   lte   image   rgs   protected   contain   csharp   

实现思路:

1.继承ComboBox

2.重写ComboBox的模板,把列表控件替换成树形控件

3.重写SelectedItem, SelectedValue,DisplayMemberPath,SelectedValuePath

效果截图:

技术图片

 

XAML代码

    
    

 cs代码

    /// 
    /// TreeSelect.xaml 的交互逻辑
    /// 
    [TemplatePart(Name = "PART_TreeView", Type = typeof(TreeView))]
    public partial class TreeSelect : ComboBox
    {
        public bool IsMulti
        {
            get { return (bool)GetValue(IsMultiProperty); }
            set { SetValue(IsMultiProperty, value); }
        }

        public static readonly DependencyProperty IsMultiProperty =
            DependencyProperty.Register("IsMulti", typeof(bool), typeof(TreeSelect), new PropertyMetadata(false));

        public new string DisplayMemberPath
        {
            get { return (string)GetValue(DisplayMemberPathProperty); }
            set { SetValue(DisplayMemberPathProperty, value); }
        }

        public new static readonly DependencyProperty DisplayMemberPathProperty =
            DependencyProperty.Register("DisplayMemberPath", typeof(string), typeof(TreeSelect));

        public new string SelectedValuePath
        {
            get { return (string)GetValue(SelectedValuePathProperty); }
            set { SetValue(SelectedValuePathProperty, value);  }
        }

        public new static readonly DependencyProperty SelectedValuePathProperty =
            DependencyProperty.Register("SelectedValuePath", typeof(string), typeof(TreeSelect));

        /// 
        /// Selected item of the TreeView
        /// 
        public new object SelectedItem
        {
            get { return (object)GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }

        public new static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register("SelectedItem", typeof(object), typeof(TreeSelect), new PropertyMetadata(null, new PropertyChangedCallback(OnSelectedItemChanged)));

        private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((TreeSelect)sender).UpdateSelectedItem();

            
        }

        public new object SelectedValue
        {
            get { return (object)GetValue(SelectedValueProperty); }
            set { SetValue(SelectedValueProperty, value); }
        }

        public new static readonly DependencyProperty SelectedValueProperty =
            DependencyProperty.Register("SelectedValue", typeof(object), typeof(TreeSelect), new PropertyMetadata(null));


        public new string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(TreeSelect));

        /// 
        /// Gets or sets text separator.
        /// 
        public string TextSeparator
        {
            get { return (string)GetValue(TextSeparatorProperty); }
            set { SetValue(TextSeparatorProperty, value); }
        }

        public static readonly DependencyProperty TextSeparatorProperty =
            DependencyProperty.Register("TextSeparator", typeof(string), typeof(TreeSelect), new PropertyMetadata(","));

        /// 
        /// Gets or sets max text length.
        /// 
        public int? MaxTextLength
        {
            get { return (int?)GetValue(MaxTextLengthProperty); }
            set { SetValue(MaxTextLengthProperty, value); }
        }

        public static readonly DependencyProperty MaxTextLengthProperty =
            DependencyProperty.Register("MaxTextLength", typeof(int?), typeof(TreeSelect));

        /// 
        /// Gets or sets text filler when text length exceeded.
        /// 
        public string ExceededTextFiller
        {
            get { return (string)GetValue(ExceededTextFillerProperty); }
            set { SetValue(ExceededTextFillerProperty, value); }
        }

        public static readonly DependencyProperty ExceededTextFillerProperty =
            DependencyProperty.Register("ExceededTextFiller", typeof(string), typeof(TreeSelect), new PropertyMetadata("..."));

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

        public TreeSelect()
        {
            Loaded -= TreeSelect_Loaded;
            Loaded += TreeSelect_Loaded;
            SizeChanged -= TreeSelect_SizeChanged;
            SizeChanged += TreeSelect_SizeChanged;
        }

        private ExtendedTreeView _treeView;

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this._treeView = Template.FindName("PART_TreeView", this) as ExtendedTreeView;
            if (this._treeView != null)
            {
                //this._treeView.SelectedItemChanged += _TreeView_SelectedItemChanged;
                _treeView.OnHierarchyMouseUp += new MouseEventHandler(OnTreeViewHierarchyMouseUp);
                _treeView.AddHandler(System.Windows.Controls.TreeViewItem.SelectedEvent, new System.Windows.RoutedEventHandler(treeview_Selected));
            }
        }

        //protected override void OnDropDownClosed(EventArgs e)
        //{
        //    base.OnDropDownClosed(e);
        //    this.SelectedItem = _treeView.SelectedItem;
        //    this.UpdateText();
        //}

        //protected override void OnDropDownOpened(EventArgs e)
        //{
        //    base.OnDropDownOpened(e);
        //    this.UpdateText();
        //}

        /// 
        /// Handles clicks on any item in the tree view
        /// 
        private void OnTreeViewHierarchyMouseUp(object sender, MouseEventArgs e)
        {
            //This line isn‘t obligatory because it is executed in the OnDropDownClosed method, but be it so
            this.SelectedItem = _treeView.SelectedItem;
            this.UpdateText(); 
            base.SelectedItem = this.SelectedItem;
            this.IsDropDownOpen = false;
        }

        private void treeview_Selected(object sender, RoutedEventArgs e)
        {
            TreeViewItem item = (e.OriginalSource as TreeViewItem);
            if (item != null)
            {
                item.BringIntoView();
            }
        }

        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            if (item is ComboBoxItem)
                return true;
            else
                return false;
        }

        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            var uie = element as FrameworkElement;

            if (!(item is ComboBoxItem))
            {
                var textBinding = new Binding(DisplayMemberPath);
                textBinding.Source = item;
                uie.SetBinding(ContentPresenter.ContentProperty, textBinding);
            }

            base.PrepareContainerForItemOverride(element, item);
        }

        private void TreeSelect_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (!IsLoaded)
                return;

            UpdateText();
        }
        private void TreeSelect_Loaded(object sender, RoutedEventArgs e)
        {
            UpdateText();
        }

        private void UpdateSelectedItem()
        {
            UpdateText();
            base.SelectedItem = this.SelectedItem;

            if (this.SelectedItem == null || string.IsNullOrEmpty(this.SelectedValuePath))
            {
                SelectedValue = null;                
            }
            else
            {
                SelectedValue = this.SelectedItem.GetType().GetProperty(SelectedValuePath).GetValue(this.SelectedItem, null);
            }
        }

        private void _TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgsobject> e)
        {
            if (!IsLoaded)
                return;           

            UpdateText();
            base.SelectedItem = this.SelectedItem;
        }

        private void UpdateText()
        {
            if (IsMulti == false)
            {
                Text = GenerateText(SelectedItem);
            }
            else
            {
                Text = GenerateText();
            }
        }

        public string GenerateText(object selectedItem)
        {
            var text = "";
            if (selectedItem == null)
            {
                text = "";
            }
            else if (selectedItem is ComboBoxItem)
            {
                var msi = selectedItem as ComboBoxItem;
                text += msi.Content.ToString();
            }
            else
            {
                if (!string.IsNullOrEmpty(DisplayMemberPath) && selectedItem.GetType().GetProperty(DisplayMemberPath) != null)
                    text += selectedItem.GetType().GetProperty(DisplayMemberPath).GetValue(selectedItem, null).ToString();
                else
                    text += selectedItem.ToString();

                if (selectedItem.GetType().GetProperty("IsSelected") != null)
                {
                    selectedItem.GetType().GetProperty("IsSelected").SetValue(selectedItem, true);
                }
            }

            return text;
        }

        public string GenerateText()
        {
            var text = "";
            var isFirst = true;

            foreach (var item in Items)
            {
                if (!isFirst)
                    text += TextSeparator;
                else
                    isFirst = false;

                if (item is ComboBoxItem)
                {
                    var msi = item as ComboBoxItem;
                    text += msi.Content.ToString();
                }
                else
                {
                    if (item.GetType().GetProperty("IsSelected") != null && item.GetType().GetProperty("IsSelected").GetValue(item, null).ToString() == "true")
                    {
                        if (!string.IsNullOrEmpty(DisplayMemberPath) && item.GetType().GetProperty(DisplayMemberPath) != null)
                            text += item.GetType().GetProperty(DisplayMemberPath).GetValue(item, null).ToString();
                        else
                            text += item.ToString();
                    }
                }

                if (MaxTextLength == null)
                {
                    if (!ValidateStringWidth(text + ExceededTextFiller))
                    {
                        if (text.Length == 0)
                            return null;
                        text = text.Remove(text.Length - 1);
                        while (!ValidateStringWidth(text + ExceededTextFiller))
                        {
                            if (text.Length == 0)
                                return null;
                            text = text.Remove(text.Length - 1);
                        }
                        return text + ExceededTextFiller;
                    }
                }
                else if (text.Length >= MaxTextLength)
                {
                    return text.Cut((int)MaxTextLength, ExceededTextFiller);
                }
            }
            return text;
        }

        private bool ValidateStringWidth(string text)
        {
            var size = MeasureString(text);
            if (size.Width > (ActualWidth - Padding.Left - Padding.Right - 30))
                return false;
            else
                return true;

        }

        private Size MeasureString(string candidate)
        {
            var formattedText = new FormattedText(candidate, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(FontFamily, FontStyle, FontWeight, FontStretch), FontSize, Brushes.Black, new NumberSubstitution(), TextFormattingMode.Display);

            return new Size(formattedText.Width, formattedText.Height);
        }
    }

使用:

 

 完成,这个还支持多选的,没有完全完成,待续。

Wpf实现TreeSelect

标签:closed   on()   bottom   lte   image   rgs   protected   contain   csharp   

原文地址:https://www.cnblogs.com/akwkevin/p/14199966.html


评论


亲,登录后才可以留言!