代码之家  ›  专栏  ›  技术社区  ›  Alan Wayne

如何在TreeView中禁用修饰元素时启用编辑修饰器?

  •  0
  • Alan Wayne  · 技术社区  · 6 年前

    水渍险

    我有一个TreeView(见下文),我为它创建了一个编辑装饰器。 一切正常。但是,我想在编辑过程中禁用TreeView。当TreeView被禁用时——以及被修饰以进行编辑的元素——修饰器也被禁用。

    如何禁用TreeView(isEnabled=false),但仍允许启用装饰器进行编辑?

    短暂性脑缺血发作

    namespace Doctor_Desk.Views.Adorners
    {
        public class EditSelectedItemAdorner : Adorner
        {
            private VisualCollection _Visuals;
            private UIElement _UIElement;
            private bool _IsCancel = false;
            private TextBox _Textbox;
    
            protected override int VisualChildrenCount
            {
                get
                {
                    return _Visuals.Count;
                }
            }
    
            // Be sure to call the base class constructor.
            public EditSelectedItemAdorner(UIElement adornedElement, IConsultantTreeItem selectedItem)
              : base(adornedElement)
            {
                _UIElement = adornedElement;
                adornedElement.Visibility = Visibility.Hidden;
    
                _Textbox = new TextBox
                {
                    Background = Brushes.Pink,
                    Text = selectedItem.GetText()
                };
    
                // The VisualCollection will hold the content of this Adorner.
                _Visuals = new VisualCollection(this)
                {
                    // The _Textbox is a logical child of the VisualCollection of the Adorner. The ArrangeOverride and MeasureOverride 
                    // will set up the Grid control for correct rendering.
                    _Textbox   // Adding a single control for display.
                };
    
            }
    
    
    
            /// The adorner placement is always relative to the top left corner of the adorned element. The children of the adorner are located by
            /// implementing ArrangeOverride. The only other way to position the Adorner content is to use the AdornerPanel Class 
            /// with it's AdornerPlacementCollection Methods.
            /// 
            /// Overriding the default ArrangeOverride and MeasureOverride allows a control to be placed and diplayed in the VisualCollection.
            protected override Size ArrangeOverride(Size finalSize)
            {
                //TextBox child = _Visuals[0] as TextBox;
                //FrameworkElement element = _UIElement as FrameworkElement;
                //if (element != null)
                //{
                //    Size textBoxSize = new Size(Math.Max(150, element.DesiredSize.Width), Math.Max(30, element.DesiredSize.Height));
                //    Point location = new Point((this.Width - textBoxSize.Width) / 2,
                //        (textBoxSize.Height - this.Height) / 2);
                //    child.Arrange(new Rect(location, textBoxSize));
                //}
    
                TextBox child = _Visuals[0] as TextBox;
                Rect adornedElementRect = new Rect(this.AdornedElement.DesiredSize);
                child.Arrange(adornedElementRect);
    
                return base.ArrangeOverride(finalSize);
            }
    
            // Overriding the default ArrangeOverride and MeasureOverride allows a control to be diplayed in the VisualCollection.
            protected override Size MeasureOverride(Size constraint)
            {
                _Textbox.Measure(constraint);
                return _Textbox.DesiredSize;
            }
    
            protected override Visual GetVisualChild(int index)
            {
                return _Visuals[index];
            }
    
            // A common way to implement an adorner's rendering behavior is to override the OnRender
            // method, which is called by the layout system as part of a rendering pass.
            protected override void OnRender(DrawingContext drawingContext)
            {
                Rect adornedElementRect = new Rect(this.AdornedElement.DesiredSize);
    
                // Some arbitrary drawing implements.
                SolidColorBrush renderBrush = new SolidColorBrush(Colors.Green)
                {
                    Opacity = 0.2
                };
                Pen renderPen = new Pen(new SolidColorBrush(Colors.Navy), 1.5);
                double renderRadius = 5.0;
    
                // Draw a circle at each corner.
                drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopLeft, renderRadius, renderRadius);
                drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopRight, renderRadius, renderRadius);
                drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomLeft, renderRadius, renderRadius);
                drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomRight, renderRadius, renderRadius);
            }
    
    
    
            public string Text
            {
                get { return (string)GetValue(TextProperty); }
                set { SetValue(TextProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty TextProperty =
                DependencyProperty.Register("Text", typeof(string), typeof(EditSelectedItemAdorner), new PropertyMetadata(string.Empty));
    
    
        }
    }
    
    
    
     <TreeView  Grid.Row="2"  Grid.Column="2"  Grid.RowSpan="4"  Width="400"
                       ItemsSource="{Binding SpecialityTree}" 
                       >
                <TreeView.Resources>
    
    
                    <HierarchicalDataTemplate DataType="{x:Type tree:SpecialityTreeItem}" ItemsSource="{Binding Offices}" >
                        <TextBlock Text="{Binding Title}" />
                    </HierarchicalDataTemplate>
    
                    <HierarchicalDataTemplate DataType="{x:Type tree:OfficeTreeItem}" ItemsSource="{Binding Doctors}">
                        <TextBlock Text="{Binding Name}" />
                    </HierarchicalDataTemplate>
    
                    <DataTemplate DataType="{x:Type tree:DoctorTreeItem}">
                        <StackPanel Orientation="Horizontal" >
                            <TextBlock Text="{Binding FirstName}" />
                            <TextBlock Text="  " />
                            <TextBlock Text="{Binding LastName}" />
                        </StackPanel>
                    </DataTemplate>
                </TreeView.Resources>
                <TreeView.ItemContainerStyle>
                    <Style TargetType="TreeViewItem">
                        <Setter Property="IsExpanded" Value="True"/>
                    </Style>
                </TreeView.ItemContainerStyle>
    
                <i:Interaction.Behaviors>
                    <b:ConsultantTreeViewBehavior 
                        EditSelectedItem="{Binding IsEditing}"
                        SelectedItem="{Binding SelectedTreeItem, Mode=TwoWay}"
                        Text="{Binding EditingResult, Mode=OneWayToSource}"
                         />
                </i:Interaction.Behaviors>
    
    
    
    
    
    namespace Doctor_Desk.Views.Behaviors
    {
        public class ConsultantTreeViewBehavior : Behavior<TreeView>
        {
            protected override void OnAttached()
            {
                base.OnAttached();
    
                AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
            }
    
            protected override void OnDetaching()
            {
                base.OnDetaching();
    
                if (AssociatedObject != null)
                {
                    AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
                }
            }
    
            private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
            {
                SelectedItem = e.NewValue;
            }
    
            #region SelectedItem Property
    
            public object SelectedItem
            {
                get { return GetValue(SelectedItemProperty); }
                set { SetValue(SelectedItemProperty, value); }
            }
    
            public static readonly DependencyProperty SelectedItemProperty =
                DependencyProperty.Register("SelectedItem", typeof(object), typeof(ConsultantTreeViewBehavior), new UIPropertyMetadata(null, OnSelectedItemChanged));
    
            private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
            {
                if (e.NewValue is TreeViewItem item)
                {
                    item.SetValue(TreeViewItem.IsSelectedProperty, true);
                }
            }
    
            #endregion
    
            #region [EditSelectedItem]
    
            public bool EditSelectedItem
            {
                get { return (bool)GetValue(EditSelectedItemProperty); }
                set { SetValue(EditSelectedItemProperty, value); }
            }
    
            private EditSelectedItemAdorner _Adorner;
    
            public AdornerLayer myAdornerLayer { get; set; }
    
            // Using a DependencyProperty as the backing store for EditSelectedItem.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty EditSelectedItemProperty =
                DependencyProperty.Register("EditSelectedItem", typeof(bool), typeof(ConsultantTreeViewBehavior), new PropertyMetadata(false, OnEditSelectedItem));
    
            private static void OnEditSelectedItem(DependencyObject sender, DependencyPropertyChangedEventArgs e)
            {
                if ((bool)e.NewValue)
                {
                    var d = sender as ConsultantTreeViewBehavior;
                    var h = d.AssociatedObject as TreeView;
    
                    TreeViewItem tvi = h
                           .ItemContainerGenerator
                           .ContainerFromItemRecursive(h.SelectedItem);
    
                    if (tvi is UIElement myItem)
                    {
                        d._Adorner = new EditSelectedItemAdorner(myItem, (IConsultantTreeItem)h.SelectedItem);
    
                        // Must have BindingMode.TwoWay for the Adorner to update this ConsultantTreeViewBehavior.
                        var bindingText = new Binding
                        {
                            Source = d,
                            Path = new PropertyPath(TextProperty),
                            Mode = BindingMode.TwoWay
                        };
                        // The TextProperty binds the Text from the EditSelectedItemAdorner to the ConsultantManagerViewModel.
                        BindingOperations.SetBinding(d._Adorner, EditSelectedItemAdorner.TextProperty, bindingText);
    
                        d.myAdornerLayer = AdornerLayer.GetAdornerLayer(myItem);
                        d.myAdornerLayer.Add(d._Adorner);
                    }
                }
            }
    
            #endregion
    
            #region[Text - xaml binding]
            public string Text
            {
                get { return (string)GetValue(TextProperty); }
                set { SetValue(TextProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty TextProperty =
                DependencyProperty.Register("Text", typeof(string), typeof(ConsultantTreeViewBehavior), new PropertyMetadata(string.Empty,
                    (s, e) =>
                    {
    
                    }));
            #endregion
    
        }
    
    }
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   Alan Wayne    6 年前

    那么,在任何其他答案的leu中,在treeview中禁用选择似乎会禁用treeview的所有元素——包括所选分支。当选定的分支被禁用时,其编辑修饰器也将禁用。因此,我的解决方法只是覆盖正在显示的TreeView的那部分。

    特别是,在onrender覆盖中,添加:

     // Find offset of selected item from top of the tree.
            GeneralTransform gt = AdornedElement.TransformToVisual(_TreeView);
            Point offset_to_tree_top = gt.Inverse.Transform(new Point(0, 0));
            drawingContext.DrawRectangle(Brushes.DimGray, null, new Rect( 
            offset_to_tree_top, _TreeView.DesiredSize));
    

    这会在整棵树上添加一个灰色,除了编辑装饰器。因此,用户无法选择任何其他树项。

    推荐文章