سؤال

مستوحاة من هذا المشنور, ، أحاول استخدام TreeView داخل المنبثقة التلقائية لـ AutoCompletebox لإظهار البيانات الهرمية.

هذا ما فعلته:

  1. لقد صنعت TreeView الخاصة بي التي تنفذ IselectionAdapter (لست متأكدًا من أنها مثالية)

  2. تحرير قالب outocompletebox وقم بتغيير المحدد إلى TreeView الخاص بي

  3. جرب ربط iewmodel الخاص بي به

للأسف هذا لا يعمل. لقد راجعت TreeView الجديد مع نفس الربط لنفس الكائن ويعمل بشكل محافظ عندما يكون خارج قالب CompleteBox.

اي فكرة؟ أي طريقة خاصة لتنفيذ iselectionAdapter لـ TreeView؟ هل فاتني شيء؟

لا يمكن العثور على أي مثال على الويب ...

شكرًا.

هل كانت مفيدة؟

المحلول

تمكنت من كتابتها في النهاية.

جعل التحكم المخصص لذلك. لا يزال يتعين صقله ، لكنه يعمل بشكل جيد:

generic.xaml:

<ControlTemplate x:Key="CommonValidationToolTipTemplate" TargetType="ToolTip">
    <Grid x:Name="Root" Margin="5,0" Opacity="0" RenderTransformOrigin="0,0">
        <Grid.RenderTransform>
            <TranslateTransform x:Name="Translation" X="-25"/>
        </Grid.RenderTransform>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="OpenStates">
                <VisualStateGroup.Transitions>
                    <VisualTransition GeneratedDuration="0"/>
                    <VisualTransition GeneratedDuration="0:0:0.2" To="Open">
                        <Storyboard>
                            <DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="Translation">
                                <DoubleAnimation.EasingFunction>
                                    <BackEase Amplitude=".3" EasingMode="EaseOut"/>
                                </DoubleAnimation.EasingFunction>
                            </DoubleAnimation>
                            <DoubleAnimation Duration="0:0:0.2" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>
                        </Storyboard>
                    </VisualTransition>
                </VisualStateGroup.Transitions>
                <VisualState x:Name="Closed">
                    <Storyboard>
                        <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Open">
                    <Storyboard>
                        <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="Translation"/>
                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Border Background="#052A2E31" CornerRadius="5" Margin="4,4,-4,-4"/>
        <Border Background="#152A2E31" CornerRadius="4" Margin="3,3,-3,-3"/>
        <Border Background="#252A2E31" CornerRadius="3" Margin="2,2,-2,-2"/>
        <Border Background="#352A2E31" CornerRadius="2" Margin="1,1,-1,-1"/>
        <Border Background="#FFDC000C" CornerRadius="2">
            <TextBlock Foreground="White" MaxWidth="250" Margin="8,4,8,4" TextWrapping="Wrap" Text="{Binding (Validation.Errors)[0].ErrorContent}" UseLayoutRounding="false"/>
        </Border>
    </Grid>
</ControlTemplate>
<Style TargetType="local:AutoCompleteTreeView"
       xmlns:System="clr-namespace:System;assembly=mscorlib">
    <Setter Property="IsTabStop" Value="False"/>
    <Setter Property="Padding" Value="2"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="BorderBrush">
        <Setter.Value>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FFA3AEB9" Offset="0"/>
                <GradientStop Color="#FF8399A9" Offset="0.375"/>
                <GradientStop Color="#FF718597" Offset="0.375"/>
                <GradientStop Color="#FF617584" Offset="1"/>
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
    <Setter Property="Background" Value="#FFFFFFFF"/>
    <Setter Property="Foreground" Value="#FF000000"/>
    <Setter Property="MinWidth" Value="45"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:AutoCompleteTreeView">
                <Grid Opacity="{TemplateBinding Opacity}">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="PopupStates">
                            <VisualStateGroup.Transitions>
                                <VisualTransition GeneratedDuration="0:0:0.1" To="PopupOpened"/>
                                <VisualTransition GeneratedDuration="0:0:0.2" To="PopupClosed"/>
                            </VisualStateGroup.Transitions>
                            <VisualState x:Name="PopupOpened">
                                <Storyboard>
                                    <DoubleAnimation To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PopupBorder"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="PopupClosed">
                                <Storyboard>
                                    <DoubleAnimation To="0.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PopupBorder"/>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="ValidationStates">
                            <VisualState x:Name="Valid"/>
                            <VisualState x:Name="InvalidUnfocused">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="InvalidFocused">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" Storyboard.TargetName="validationTooltip">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <System:Boolean>True</System:Boolean>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <TextBox x:Name="Text" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" IsTabStop="True" Margin="0" Padding="{TemplateBinding Padding}" Style="{TemplateBinding TextBoxStyle}"/>
                    <Border x:Name="ValidationErrorElement" BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1" Visibility="Collapsed">
                        <ToolTipService.ToolTip>
                            <ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource CommonValidationToolTipTemplate}">
                                <ToolTip.Triggers>
                                    <EventTrigger RoutedEvent="Canvas.Loaded">
                                        <BeginStoryboard>
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="validationTooltip">
                                                    <DiscreteObjectKeyFrame KeyTime="0">
                                                        <DiscreteObjectKeyFrame.Value>
                                                            <System:Boolean>true</System:Boolean>
                                                        </DiscreteObjectKeyFrame.Value>
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </EventTrigger>
                                </ToolTip.Triggers>
                            </ToolTip>
                        </ToolTipService.ToolTip>
                        <Grid Background="Transparent" HorizontalAlignment="Right" Height="12" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12">
                            <Path Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" Fill="#FFDC000C" Margin="1,3,0,0"/>
                            <Path Data="M 0,0 L2,0 L 8,6 L8,8" Fill="#ffffff" Margin="1,3,0,0"/>
                        </Grid>
                    </Border>
                    <Popup x:Name="Popup">
                        <Grid Opacity="{TemplateBinding Opacity}">
                            <Border x:Name="PopupBorder" BorderThickness="0" Background="#11000000" HorizontalAlignment="Stretch" Opacity="0">
                                <Border.RenderTransform>
                                    <TranslateTransform X="1" Y="1"/>
                                </Border.RenderTransform>
                                <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0" HorizontalAlignment="Stretch" Opacity="1.0" Padding="0">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                            <GradientStop Color="#FFDDDDDD" Offset="0"/>
                                            <GradientStop Color="#AADDDDDD" Offset="1"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                    <Border.RenderTransform>
                                        <TransformGroup>
                                            <TranslateTransform X="-1" Y="-1"/>
                                        </TransformGroup>
                                    </Border.RenderTransform>
                                    <local:TreeViewSelectionAdapter x:Name="SelectionAdapter" BorderThickness="0" Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ItemTemplate="{TemplateBinding ItemTemplate}" ItemContainerStyle="{TemplateBinding ItemContainerStyle}" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
                                </Border>  
                            </Border>  
                        </Grid>
                    </Popup>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

expletetreeview.cs:

public class AutoCompleteTreeView : AutoCompleteBox
{
    public AutoCompleteTreeView()
    {
        DefaultStyleKey = typeof(AutoCompleteTreeView);
    }
}

TreeViewSelectionAdapter.cs:

public class TreeViewSelectionAdapter : TreeView, ISelectionAdapter
{
    private object lastSelectedItem = null;

    /// <summary>
    ///This prevents the text box of the AutoCompleteBox control from being updated continuously.
    /// </summary>
    private bool IgnoreAnySelection { get; set; }

    /// <summary>
    /// An event that indicates that a selection is complete and has been
    /// made, effectively a commit action.
    /// </summary>
    public event RoutedEventHandler Commit;

    /// <summary>
    /// An event that indicates that the selection operation has been
    /// canceled.
    /// </summary>
    public event RoutedEventHandler Cancel;

    /// <summary>
    /// Initializes a new instance of the SelectorSelectionAdapter class.
    /// </summary>
    public TreeViewSelectionAdapter()
    {
        base.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(OnSelectionChanged);
        MouseLeftButtonUp += OnSelectorMouseLeftButtonUp;

    }

    void OnSelectionChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {

        if (IgnoreAnySelection)
        {
            return;
        }

        SelectionChangedEventHandler handler = this.SelectionChanged;
        if (handler != null)
        {
            IList oldSelectedItem = new List<object>();
            if (lastSelectedItem != null)
                oldSelectedItem.Add(lastSelectedItem);

            if (SelectionChanged != null)
                handler(this, new SelectionChangedEventArgs(oldSelectedItem, new List<object> { this.SelectedItem }));

            lastSelectedItem = this.SelectedItem;

        }
    }

    public new object SelectedItem
    {
        get
        {
            return base.SelectedItem;
        }

        set
        {
            this.SelectItem(value);
        }
    }

    /// <summary>
    /// Handles the mouse left button up event on the selector control.
    /// </summary>
    private void OnSelectorMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        IgnoreAnySelection = false;

        OnSelectionChanged(this, null);
        OnCommit(this, new RoutedEventArgs());
    }


    public event SelectionChangedEventHandler SelectionChanged;



    /// <summary>
    /// Gets or sets the items source.
    /// </summary>
    public new IEnumerable ItemsSource
    {
        get { return base.ItemsSource; }

        set
        {
            if (base.ItemsSource != null)
            {
                INotifyCollectionChanged notify = base.ItemsSource as INotifyCollectionChanged;
                if (notify != null)
                {
                    notify.CollectionChanged -= OnCollectionChanged;
                }
            }

            base.ItemsSource = value;

            if (base.ItemsSource != null)
            {
                INotifyCollectionChanged notify = base.ItemsSource as INotifyCollectionChanged;
                if (notify != null)
                {
                    notify.CollectionChanged += OnCollectionChanged;
                }
            }
        }
    }

    /// <summary>
    /// Handles the CollectionChanged event, resetting the selection
    /// ignore flag.
    /// </summary>
    private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        IgnoreAnySelection = true;
    }


    /// <summary>
    /// Process a key down event.
    /// </summary>
    public void HandleKeyDown(KeyEventArgs e)
    {
        switch (e.Key)
        {
            case Key.Enter:
                IgnoreAnySelection = false;
                OnCommit(this, e);
                e.Handled = true;
                break;


            case Key.Down:
                if ((ModifierKeys.Alt & Keyboard.Modifiers) == ModifierKeys.None)
                {
                    IgnoreAnySelection = true;
                    //SelectedIndexIncrement();
                    TreeView tv = this.FindName("SelectionAdapter") as TreeView;

                    tv.KeyDown += new KeyEventHandler(tv_KeyDown);
                    tv.Focus();

                    List<TreeViewItem> ls = new List<TreeViewItem>(tv.GetContainers());
                    ls[0].Focus();
                    e.Handled = true;

                }
                break;

            case Key.Escape:
                OnCancel(this, e);
                e.Handled = true;
                break;

            default:
                break;
        }
    }

    void tv_KeyDown(object sender, KeyEventArgs e)
    {
        switch (e.Key)
        {
            case Key.Enter:

                IgnoreAnySelection = false;

                OnSelectionChanged(this, null);
                OnCommit(this, new RoutedEventArgs());
                break;
        }
    }



    /// <summary>
    /// Fires the Commit event.
    /// </summary>
    private void OnCommit(object sender, RoutedEventArgs e)
    {
        RoutedEventHandler handler = Commit;
        if (handler != null)
        {
            handler(sender, e);
        }

        AfterAdapterAction();
    }

    /// <summary>
    /// Fires the Cancel event.
    /// </summary>
    private void OnCancel(object sender, RoutedEventArgs e)
    {
        RoutedEventHandler handler = Cancel;
        if (handler != null)
        {
            handler(sender, e);
        }

        AfterAdapterAction();
    }

    /// <summary>
    /// Change the selection after the actions are complete.
    /// </summary>
    private void AfterAdapterAction()
    {
        this.SetSelectedContainer(null);
    }

    /// <summary>
    /// Initializes a new instance of a DataGridAutomationPeer.
    /// </summary>
    public AutomationPeer CreateAutomationPeer()
    {
        return new TreeViewAutomationPeer(this);
    }
}

باستخدام التحكم:

<ccontrols:AutoCompleteTreeView  x:Name="textbox" MinimumPrefixLength="1" IsEnabled="True" ItemsSource="{Binding MyNodes}"  >
        <ccontrols:AutoCompleteTreeView.ItemTemplate>
            <hirarch:HierarchicalDataTemplate ItemsSource="{Binding MyNodes}" >
                <TextBlock Text="{Binding Name}" />
            </hirarch:HierarchicalDataTemplate>
        </ccontrols:AutoCompleteTreeView.ItemTemplate>
    </ccontrols:AutoCompleteTreeView>

كائنات التسلسل الهرمي:

public class Node
{
    public string Name { get; set; }
    public List<Node> MyNodes { get; set; }

    public override string ToString()
    {
        return Name;
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top