问题描述
我正在开发移动应用程序,有点通过按顺序拖放图像来模拟如何构建台式计算机。我使用 DropGestureRecognizer
将 AllowDrop
设置为 True
用于放置区 Image
控件和 DragGestureRecognizer
并将 CanDrag
设置为 True
用于拖动 Image
对象。
这个想法是 Drag Image Objects
会被拖放到 Drop Zone Image Control
上,如果他们放下了正确的 Drag Image
,Drop Zone
会接受它作为 {{1 }} 和另一个 Image.source
将堆叠在它的前面以与下一个台式计算机组件一起使用。否则,它将被拒绝,Drop Zone
将设置为 Image.source
或 empty
。
但是,我遇到了一个奇怪的问题,在拖动的第一个不正确的图像上,null
被属性重置为 Image.source
或 empty
,但在实际的 UI 上,它没有。在随后的 EventHandler 执行中,它确实会被重置。我在 null
上有一个 TapGestureRecognizer
来检查是否有 Drop Zone
集。
如果我的解释有点混乱,我很抱歉,因为英语不是我的母语,我很难解释。所以请参考下面的 GIF 示例和我的代码:
视图(.xaml):
Image.source
查看代码 (.xaml.cs):
<ContentPage.Content>
<Grid RowDeFinitions="Auto,60,*"
ColumnDeFinitions="*">
<RelativeLayout Grid.Row="0" Grid.Column="0" HorizontalOptions="Center">
<Image x:Name="imgCaseDropZone"
RelativeLayout.XConstraint="0"
RelativeLayout.YConstraint="0"
HeightRequest="{Binding ScreenWidth}"
WidthRequest="{Binding ScreenWidth}"
PropertyChanged="CaseDropZone_PropertyChanged"
BackgroundColor="LightGray">
<Image.GestureRecognizers>
<DropGestureRecognizer AllowDrop="True" />
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</Image.GestureRecognizers>
</Image>
</RelativeLayout>
<Label Grid.Row="1" Grid.Column="0"
x:Name="lblDirections"
Text="Directions: Drag the components below in its proper order to the drop zone above."
TextColor="Black"
Padding="10"
VerticalOptions="CenterandExpand"
HorizontalOptions="CenterandExpand" />
<ScrollView Grid.Row="2"
Orientation="Horizontal"
Margin="5">
<StackLayout Orientation="Horizontal">
<!--#region Case -->
<Grid RowDeFinitions="*,Auto"
IsVisible="{Binding CaseIsVisible}">
<Image Grid.Row="0"
x:Name="imgCaseDragObject"
Source="{Binding CaseImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding CaseLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Case Cover -->
<Grid RowDeFinitions="*,Auto"
IsVisible="{Binding CaseCoverIsVisible}">
<Image Grid.Row="0"
Source="{Binding CaseCoverImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding CaseCoverLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Case Screw -->
<Grid RowDeFinitions="*,Auto"
IsVisible="{Binding CaseScrewIsVisible}">
<Image Grid.Row="0"
Source="{Binding CaseScrewImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding CaseScrewLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Hard disk Drive -->
<Grid RowDeFinitions="*,Auto"
IsVisible="{Binding HarddiskDriveIsVisible}">
<Image Grid.Row="0"
Source="{Binding HarddiskDriveImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding HarddiskDriveLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Heatsink -->
<Grid RowDeFinitions="*,Auto"
IsVisible="{Binding HeatsinkIsVisible}">
<Image Grid.Row="0"
Source="{Binding HeatsinkImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding HeatsinkLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Memory Module -->
<Grid RowDeFinitions="*,Auto"
IsVisible="{Binding MemoryModuleIsVisible}">
<Image Grid.Row="0"
Source="{Binding MemoryModuleImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding MemoryModuleLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region motherboard -->
<Grid RowDeFinitions="*,Auto"
IsVisible="{Binding motherboardIsVisible}">
<Image Grid.Row="0"
Source="{Binding motherboardImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding motherboardLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region motherboard Screw -->
<Grid RowDeFinitions="*,Auto"
IsVisible="{Binding motherboardScrewIsVisible}">
<Image Grid.Row="0"
Source="{Binding motherboardScrewImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding motherboardScrewLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Power Supply -->
<Grid RowDeFinitions="*,Auto"
IsVisible="{Binding PowerSupplyIsVisible}">
<Image Grid.Row="0"
Source="{Binding PowerSupplyImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding PowerSupplyLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
<!--#region Processor -->
<Grid RowDeFinitions="*,Auto"
IsVisible="{Binding ProcessorIsVisible}">
<Image Grid.Row="0"
Source="{Binding ProcessorImgSource}">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Row="1"
Text="{Binding ProcessorLabel}"
TextColor="White"
FontSize="Medium"
BackgroundColor="Gray"
HorizontalTextAlignment="Center" />
</Grid>
<!--#endregion-->
</StackLayout>
</ScrollView>
</Grid>
</ContentPage.Content>
视图模型 (.cs):
[XamlCompilation(XamlCompilationoptions.Compile)]
public partial class AssemblyPage : ContentPage
{
string caseSource;
public AssemblyPage()
{
InitializeComponent();
}
int dragCount = 0;
private void CaseDropZone_PropertyChanged(object sender,PropertyChangedEventArgs e)
{
if (e.PropertyName == "Source")
{
caseSource = imgCaseDropZone.source.ToString().Split(':').Last().Trim();
if (string.IsNullOrEmpty(caseSource))
{
return;
}
if (caseSource != "img_assembly_case.png")
{
imgCaseDropZone.source = string.Empty;
lblDirections.Text = $"Drag Count: {++dragCount}";
}
}
}
private void TapGestureRecognizer_Tapped(object sender,EventArgs e)
{
Application.Current.MainPage.displayAlert("",$"{imgCaseDropZone.source}","OK");
}
}
GIF 中的当前构建演示:https://imgur.com/a/oLeM9DV(我无法直接链接 GIF,因为它太大)
解决方法
因为触发PropertyChanged
事件时,拖放动作已经完成,图片已经自动设置到目标。
我们可以在使用 DragOver
事件将其拖到目标上方时立即做出判断。然后在拖放完成时使用 Drop
事件进行操作。
例如更改图片的代码(imgCaseDropZone
):
<Image x:Name="imgCaseDropZone"
RelativeLayout.XConstraint="0"
RelativeLayout.YConstraint="0"
RelativeLayout.WidthConstraint="400"
RelativeLayout.HeightConstraint="400"
BackgroundColor="LightGray"
>
<Image.GestureRecognizers>
<DropGestureRecognizer AllowDrop="{Binding CaseIsVisible}" DragOver="CaseDropZone_DragOver" Drop="CaseDropZone_Drop"/>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</Image.GestureRecognizers>
</Image>
在后面的代码中:
private void CaseDropZone_DragOver(object sender,DragEventArgs e)
{
FileImageSource file = (FileImageSource)e.Data.Image;
string name = file.File;
if (name != "img_assembly_case.png")
{
e.Data.Image = string.Empty; // set the value string.Empty when drag it over the target,then it will fill the empty source to the image.
}
}
private async void CaseDropZone_Drop(object sender,DropEventArgs e)
{
var ctx = (BindingContext as AssemblyViewModel);
FileImageSource source = (FileImageSource)await e.Data.GetImageAsync();
string name = source.File;
if (name == "img_assembly_case.png")
{
ctx.CaseIsVisible = false;
imgMotherboardDropZone.IsVisible = true;
}
else
{
Global.Score.PCAssembly -= 5;
DisplayAlert($"Score: {Global.Score.PCAssembly}","The pre-requisite component for this part has not yet been placed.","OK");
}
}
其他图片都是这样修改的。