zoukankan      html  css  js  c++  java
  • How can I drag and drop items between data bound ItemsControls? (续)

    对本例的一些说明,例如下面的一个例子,首先是一个记载数据信息的类,
    namespace
     WpfApplication33
    {
        
    public class
     GreekGod
        {
            
    private string
     name;

            
    public string
     Name
            {
                
    get { return
     name; }
                
    set { name =
     value; }
            }

            
    private string
     description;

            
    public string
     Description
            {
                
    get { return
     description; }
                
    set { description =
     value; }
            }

            
    private string
     romanName;

            
    public string
     RomanName
            {
                
    get { return
     romanName; }
                
    set { romanName =
     value; }
            }

            
    public GreekGod(string name, string description, string
     romanName)
            {
                
    this.name =
     name;
                
    this.description =
     description;
                
    this.romanName =
     romanName;
            }
        }
    }
    然后用一个ObservableCollection集合这些数据,
    namespace
     WpfApplication33
    {
        
    public class GreekGods : ObservableCollection<GreekGod>

        {
            
    public GreekGods()
            {
                
    this.Add(new GreekGod("Aphrodite""Goddess of love, beauty and fertility""Venus"
    ));
                
    this.Add(new GreekGod("Apollo""God of prophesy, music and healing""Apollo"
    ));
                
    this.Add(new GreekGod("Ares""God of war""Mars"
    ));
                
    this.Add(new GreekGod("Artemis""Virgin goddess of the hunt""Diana"
    ));
                
    this.Add(new GreekGod("Athena""Goddess of crafts and the domestic arts""Athena"
    ));
                
    this.Add(new GreekGod("Demeter""Goddess of agriculture""Ceres"
    ));
                
    this.Add(new GreekGod("Dionysus""God of wine""Bacchus"
    ));
                
    this.Add(new GreekGod("Hephaestus""God of fire and crafts""Vulcan"
    ));
                
    this.Add(new GreekGod("Hera""Goddess of marriage""Juno"
    ));
                
    this.Add(new GreekGod("Hermes""Messenger of the Gods""Mercury"
    ));
                
    this.Add(new GreekGod("Poseidon""God of the sea, earthquakes and horses""Neptune"
    ));
                
    this.Add(new GreekGod("Zeus""Supreme God of the Olympians""Jupiter"
    ));
            }
        }
    }
    然后再xaml中把这些数据绑定到ListBox上,
    <Window x:Class="WpfApplication33.Window1"

        xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml"
        Title
    ="Window1" Height="300" Width="300"
            xmlns:local
    ="clr-namespace:WpfApplication33">
        
    <Window.Resources>
            
    <local:GreekGods x:Key="greekGods"/>
            
    <DataTemplate x:Key="itemTemplate">
                
    <TextBlock Text="{Binding Path=Name}" />
            
    </DataTemplate>
        
    </Window.Resources>

        
    <Border BorderBrush="RoyalBlue" BorderThickness="2" Margin="25" Padding="5">
            
    <StackPanel>
                
    <ListBox ItemsSource="{StaticResource greekGods}" ItemTemplate="{StaticResource itemTemplate}"
                         IsSynchronizedWithCurrentItem
    ="true" Width="200" Name="listBox"/>
                
    <Button Click="Button_Click" Margin="5">Get ListBoxItem</Button>
            
    </StackPanel>
        
    </Border>
    </Window>
    在代码中写的button click事件如下,
    private void Button_Click(object sender, RoutedEventArgs e)
            {
                var obj 
    = this.listBox.Items[0
    ];
                DependencyObject dobj 
    = this.listBox.ItemContainerGenerator.ContainerFromIndex(0
    );
                
            }

     在debug状态下我们查看obj和dobj的值和类型,如下:
    ((ListBoxItem)dobj).Content.GetType() {Name 
    = "GreekGod" FullName = "WpfApplication33.GreekGod"
    }
    obj.GetType()   {Name 
    = "GreekGod" FullName = "WpfApplication33.GreekGod"
    }
    可以看到,Items[
    0]是GreekGod,而Items[0
    ]的container是ListBoxItem类型,dobj的Content也是GreekGod。

    对于本文例子中的ItemsControl,当鼠标点击一个图片的时候,是这样确定点击的对象的,
    首先,注册了ItemsControl的PMLBD事件:
    private void DragSource_PreviewMouseLeftButtonDown(object
     sender, MouseButtonEventArgs e)
            {            
    this.sourceItemsControl =
     (ItemsControl)sender;
                Visual visual 
    = e.OriginalSource as
     Visual;

                
    this.topWindow = (Window)Utilities.FindAncestor(typeof(Window), this
    .sourceItemsControl);            
                
    this.initialMousePosition = e.GetPosition(this
    .topWindow);

                
    this.sourceItemContainer = Utilities.GetItemContainer(this
    .sourceItemsControl, visual);
                
    if (this.sourceItemContainer != null
    )
                {
                    
    this.draggedData = this
    .sourceItemContainer.DataContext;
                }
            }
    注意这里e.Source其实就是这里的sender,对应的是逻辑树中触发事件的元素,而e.OriginalSource对应的是视觉树中的触发事件的元素,所以后面会用VisualTreeHelper操作它。
    其中GetItemContainer方法如下:
    // In order to make sure it works with any control that derives from ItemsControl, this method makes no assumption about the type of that container.(it will get a ListBoxItem if it's a ListBox, a ListViewItem if it's a ListView)

    这里的意思是说因为我们不知道这个容器的类型,所以不知道对于它的每一个Item是用什么container来装的(例如ListBox的每一个Item的容器是ListBoxItem等等)。实际上这里的container是一个ContentPresenter,它的Content(这里也是DataContext)就是程序中的Picture数据。这里我们通过第一个Item得到container的类型,然后再通过在视觉树中找到用来呈现bottomMostVisual的container,它要满足也是这个类型的就可以了。
            
    public static
     FrameworkElement GetItemContainer(ItemsControl itemsControl, Visual bottomMostVisual)
            {
                FrameworkElement itemContainer 
    = null
    ;
                
    if (itemsControl != null && bottomMostVisual != null && itemsControl.Items.Count >= 1
    )
                {
                    var firstContainer 
    = itemsControl.ItemContainerGenerator.ContainerFromIndex(0
    );
                    
    if (firstContainer != null
    )
                    {
                        Type containerType 
    =
     firstContainer.GetType();

                        itemContainer 
    =
     FindAncestor(containerType, bottomMostVisual);

                        
    // Make sure that the container found belongs to the items control passed as a parameter.

                        if (itemContainer != null && itemContainer.DataContext != null)
                        {
                            FrameworkElement itemContainerVerify 
    = itemsControl.ItemContainerGenerator.ContainerFromItem(itemContainer.DataContext) as
     FrameworkElement;
                            
    if (itemContainer !=
     itemContainerVerify)
                            {
                                itemContainer 
    = null
    ;
                            }
                        }
                    }
                }
                
    return
     itemContainer;
            }
    下面是根据类型和自己找container的方法,
            
    public static
     FrameworkElement FindAncestor(Type ancestorType, Visual visual)
            {
                
    while (visual != null && !
    ancestorType.IsInstanceOfType(visual))
                {
                    visual 
    =
     (Visual)VisualTreeHelper.GetParent(visual);
                }
                
    return visual as
     FrameworkElement;
            }
  • 相关阅读:
    ip地址查询python3小工具_V0.0.1
    安恒 堡垒机 明御®运维审计与风险控制系统 部署中遇到的问题
    zping ping包工具20180605.exe测试版
    zping ping包工具20180524.exe测试版
    XSS练习平台-XSS Challenges
    温暖而又美妙的语言
    无法连接仓库:Error performing git command: /usr/local/src/git-2.9.5 ls-remote -h https://gitee.com/skynetInfo/auto-webui HEAD
    jenkins安装方式及启动配置
    Can't open file '/opt/svn/path/db/txn-current-lock': Permission denied
    centos部署maven私服
  • 原文地址:https://www.cnblogs.com/bear831204/p/1313371.html
Copyright © 2011-2022 走看看