4

Collection要素にバインドされたアイテムがあります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>
4

1 に答える 1

3

バウンティを開始すると、過去数か月間は見つけられなかった解決策が突然見つかるようです。

私は自分のソリューションを追加することに答えています。これは現在機能していますが、確実に改善できます。

私が提案しているのは、次の 2 つの異なる情報源に基づいています。

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 Toolkittoolkitから取得)

次に、3 つのドラッグ ハンドラの実装を見てみましょう。

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;
    }
}

すでに述べたように、このコードは現在機能しています。

誰かがそれを改善するための提案を持っている場合は、ここに書いてください。そうすれば、この種のことを行うためのより良い方法を確認/テストできます!

于 2013-12-03T22:17:27.893 に答える