ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – 在ItemsControl中移动行为

2019-06-29 08:56:07  阅读:295  来源: 互联网

标签:c xaml mouseevent windows-phone-8 behavior


我有一个绑定到ItemsControl元素的项集合.

我需要为每个元素启用鼠标拖动行为,但我似乎无法使其工作.

添加此代码

<i:Interaction.Behaviors>
    <el:MouseDragElementBehavior/>
</i:Interaction.Behaviors>

将使它工作,但只有我把我的项目放在ItemsControl之外.

这是ItemsControl组件的代码:

<ItemsControl ItemsSource="{Binding Items}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <utils:TemplateSelector Content="{Binding}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

难道我做错了什么?

编辑:新代码,但仍然无法工作(使用和不使用Canvas)

        <ItemsControl ItemsSource="{Binding Items}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <utils:TemplateSelector Content="{Binding}">
                        <i:Interaction.Behaviors>
                            <el:MouseDragElementBehavior/>
                        </i:Interaction.Behaviors>
                    </utils:TemplateSelector>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>

解决方法:

似乎一旦你开始赏金,你突然找到了一个你在过去几个月里找不到的解决方案.

我正在回答添加我的解决方案,目前有效,但肯定可以做得更好.

我提议的是基于两个不同的来源:

> A gesture-driven Windows Phone to-do application by Colin Eberhardt
> How to find element in visual tree? wp7回答E.Z.牡鹿

让我们从XAML开始:

<ItemsControl ItemsSource="{Binding Items}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="{StaticResource PhoneForegroundBrush}">
                <utils:TemplateSelector Content="{Binding}"/>
                <toolkit:GestureService.GestureListener>
                    <toolkit:GestureListener
                        DragStarted="GestureListener_OnDragStarted"
                        DragDelta="GestureListener_OnDragDelta"
                        DragCompleted="GestureListener_OnDragCompleted"/>
                </toolkit:GestureService.GestureListener>
            </Border>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas x:Name="WidgetsCanvas" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
</ItemsControl>

(工具包来自Windows Phone Toolkit)

现在让我们看看三个拖动处理程序的实现.

private int _zindex; //Used to keep the moved element on the top, not working for now
private FrameworkElement _movedObject; //The element that we're moving. Used to avoid moving multiple items if they overlap

private void GestureListener_OnDragStarted(object sender, DragStartedGestureEventArgs e)
{
    if (_movedObject != null) return; // We're already moving something!            
    // Initialize the drag            
    var fe = sender as FrameworkElement; // The element that we want to move
    (fe as Border).BorderThickness = new Thickness(5); // A simple effect to mark the element on the screen
    _movedObject = fe; // We set the current object to the one which is moving
    Canvas.SetZIndex(fe, _zindex++); // This should take the moved object on the top but it's not working
}

private void GestureListener_OnDragDelta(object sender, DragDeltaGestureEventArgs e)
{
    var fe = sender as FrameworkElement;
    if (!fe.Equals(_movedObject)) return; // We change the object's position only if this is the one who started the event
    var offset = DragManager.GetOffset(fe); // We get the current position
    var canvas = DragManager.FindChild<Canvas>(Application.Current.RootVisual, "ItemsCanvas"); // We need the container of our object to force it to stay inside the container
    //The new position is given by the old one plus the change reported by the event
    var horizontalOffset = offset.HorizontalValue + e.HorizontalChange;
    var verticalOffset = offset.VerticalValue + e.VerticalChange;
    // We need to check if the new position is outside our container's bounds
    if (horizontalOffset < 0) horizontalOffset = 0;
    else if (horizontalOffset > (canvas.ActualWidth - fe.ActualWidth)) horizontalOffset = canvas.ActualWidth - fe.ActualWidth;
    if (verticalOffset < 0) verticalOffset = 0;
    else if (verticalOffset > (canvas.ActualHeight - fe.ActualHeight)) verticalOffset = canvas.ActualHeight - fe.ActualHeight;           
    // Once we've got everything set, we can move our component
    DragManager.SetOffset(fe, horizontalOffset, verticalOffset);
}

private void GestureListener_OnDragCompleted(object sender, DragCompletedGestureEventArgs e)
{
    var fe = sender as FrameworkElement;                     
    (fe as Border).BorderThickness = new Thickness(0); // We undo our effect
    _movedObject = null; // The movement is done so we can reset our current object and wait for a new one to come
}

处理程序使用我称为DragManager的类.它的代码非常简单:

public static class DragManager
{
    public static void SetOffset(FrameworkElement fe, double horizontalOffset, double verticalOffset)
    {
        var trans = new TranslateTransform
        {
            X = horizontalOffset,
            Y = verticalOffset
        };
        // I don't know what may change, in terms of performance, between applying the transform or just changing the margins. I'm using the margins because the transform may be needed for some other purpose
        //fe.RenderTransform = trans;            
        fe.Margin = new Thickness(horizontalOffset, verticalOffset, 0, 0); // We just change our object's margins to reflect its new position
        // We store the current position in the objects Tag (maybe there's a better solution but I'm quite new to C#/xaml)
        fe.Tag = new Offset
        {
            VerticalValue = verticalOffset,
            HorizontalValue = horizontalOffset,
            Transform = trans
        };
    }

    public static Offset GetOffset(FrameworkElement fe)
    {
        if (fe.Tag == null) fe.Tag = new Offset();
        return (Offset)fe.Tag;
    }

    public struct Offset
    {
        public double HorizontalValue { get; set; }
        public double VerticalValue { get; set; }
        public TranslateTransform Transform { get; set; }
    }

    public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
    {
        // Confirm parent and childName are valid. 
        if (parent == null)
        {
            return null;
        }

        T foundChild = null;

        var childrenCount = VisualTreeHelper.GetChildrenCount(parent);
        for (var i = 0; i < childrenCount; i++)
        {
            var child = VisualTreeHelper.GetChild(parent, i);
            // If the child is not of the request child type child
            var childType = child as T;
            if (childType == null)
            {
                // recursively drill down the tree
                foundChild = FindChild<T>(child, childName);

                // If the child is found, break so we do not overwrite the found child. 
                if (foundChild != null)
                {
                    break;
                }
            }
            else if (!String.IsNullOrEmpty(childName))
            {
                var frameworkElement = child as FrameworkElement;
                // If the child's name is set for search
                if (frameworkElement != null && frameworkElement.Name == childName)
                {
                    // if the child's name is of the request name
                    foundChild = (T)child;
                    break;
                }

                // Need this in case the element we want is nested
                // in another element of the same type
                foundChild = FindChild<T>(child, childName);
            }
            else
            {
                // child element found.
                foundChild = (T)child;
                break;
            }
        }

        return foundChild;
    }
}

正如我已经说过的,这段代码现在正在运行.

如果有人提出改进建议,请在此处写一下,以便我可以看到/测试更好的方法来做这种事情!

标签:c,xaml,mouseevent,windows-phone-8,behavior
来源: https://codeday.me/bug/20190629/1324828.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有