我已使用 XAML 标记成功将 DrogGestureRecognizer 的 Drop 事件绑定到 CodeBehind,如下所示:
<Label Text="MyTestItem" >
<Label.GestureRecognizers>
<DropGestureRecognizer AllowDrop="True" Drop="DropGestureRecognizer_Drop_Item"/>
</Label.GestureRecognizers>
</Label>
但是,我需要在 C# 代码中完成同样的事情,因为我正在创建一个由于递归而必须动态构建的视图/控件。我的要求是从事件中获取两个参数(sender 和 DropEventArgs)。我愿意接受与 CodeBehind 或 ViewModel 一起使用的解决方案。
下面是我的尝试,但是我在多重绑定方面遇到了困难。你可以在代码中看到我的评论:
RelativeBindingSource rbs2 = new RelativeBindingSource(RelativeBindingSourceMode.FindAncestorBindingContext, ancestorType: typeof(TreeViewPageViewModel));
DropGestureRecognizer dropgGr = new DropGestureRecognizer { AllowDrop = true };
dropgGr.Bind(DropGestureRecognizer.DropCommandProperty,
mode: BindingMode.OneTime,
source: rbs2,
path: "DropGestureRecognizerDropCommand"
);
dropgGr.SetBinding(DropGestureRecognizer.DropCommandParameterProperty, new MultiBinding
{
Bindings = new Collection<BindingBase>
{
new Binding("."), // Is this the sender?
new Binding("") // How to set the DropEvenArgs here? x:TypeArguments="DropEventArgs"
}
});
label.GestureRecognizers.Add(dropgGr);
已解决: 目标是允许我的控件从一个标签拖放到控件内的另一个标签,而不是外部桌面拖/放集成。我已经能够将 Flyout 菜单附加到我的标签和 TapGestureRecognizer,并使用下面的代码让它成功调用我的 ViewModel 中的命令。
RelativeBindingSource rbs = new RelativeBindingSource(RelativeBindingSourceMode.FindAncestorBindingContext, ancestorType: typeof(ITreeViewPageViewModel));
// Context Menu --------------------------------------
var menuItem1 = new MenuFlyoutItem
{
Text = "Delete Item",
CommandParameter = xamlItem.ItemId
};
menuItem1.Bind(MenuFlyoutItem.CommandProperty,
mode: BindingMode.OneTime,
source: rbs,
path: "DeleteItemCommand"
);
var menuFlyout = new MenuFlyout();
menuFlyout.Add(menuItem1);
FlyoutBase.SetContextFlyout(label, menuFlyout);
// TagGesture ----------------------------------------
TapGestureRecognizer tgr = new TapGestureRecognizer
{
Buttons = ButtonsMask.Primary,
CommandParameter = xamlItem.ItemId,
NumberOfTapsRequired = 2
};
tgr.Bind(TapGestureRecognizer.CommandProperty,
mode: BindingMode.OneTime,
source: rbs,
path: "ItemSelectedCommand"
);
label.GestureRecognizers.Add(tgr);
在上面的示例中,请注意正在设置 commandParameter,但在本例中,参数是我的数据中的 ID。 我的 DragDrop 手势真正需要的是附加到现有的 Drop“事件”而不是“命令”。事实证明这出奇的简单:
DropGestureRecognizer dropGr = new DropGestureRecognizer { AllowDrop = true };
dropGr.Drop += DropGr_Drop_Item;
label.GestureRecognizers.Add(dropGr);
// This method is in the same class as the above code, and since I need to call a method in my
// ViewModel you can see the last line that is used to accomplish this.
private void DropGr_Drop_Item(object? sender, DropEventArgs e)
{
var data = e.Data.Properties["Text"].ToString();
var sourceItemId = e.Data.Properties["ItemId"].ToString();
var label = (sender as Element)?.Parent as Label;
var targetItemId = label.StyleId.Substring(5);
(this.BindingContext as ITreeViewPageViewModel).ReOrderItems(sourceItemId, targetItemId);
}
我的 DragDrop 手势真正需要的是附加到现有的 Drop“事件”而不是“命令”。事实证明这出奇的简单:
DropGestureRecognizer dropGr = new DropGestureRecognizer { AllowDrop = true };
dropGr.Drop += DropGr_Drop_Item;
label.GestureRecognizers.Add(dropGr);
// This method is in the same class as the above code, and since I need to call a method in my
// ViewModel you can see the last line that is used to accomplish this.
private void DropGr_Drop_Item(object? sender, DropEventArgs e)
{
var data = e.Data.Properties["Text"].ToString();
var sourceItemId = e.Data.Properties["ItemId"].ToString();
var label = (sender as Element)?.Parent as Label;
var targetItemId = label.StyleId.Substring(5);
(this.BindingContext as ITreeViewPageViewModel).ReOrderItems(sourceItemId, targetItemId);
}