PropertyChanged 事件在第一次运行时不反映新的 Image.Source

问题描述

我正在开发移动应用程序,有点通过按顺序拖放图像来模拟如何构建台式计算机。我使用 DropGestureRecognizerAllowDrop 设置为 True 用于放置区 Image 控件和 DragGestureRecognizer 并将 CanDrag 设置为 True用于拖动 Image 对象。

这个想法是 Drag Image Objects 会被拖放到 Drop Zone Image Control 上,如果他们放下了正确的 Drag ImageDrop Zone 会接受它作为 {{1 }} 和另一个 Image.source 将堆叠在它的前面以与下一个台式计算机组件一起使用。否则,它将被拒绝,Drop Zone 将设置为 Image.sourceempty

但是,我遇到了一个奇怪的问题,在拖动的第一个不正确的图像上,null属性重置为 Image.sourceempty,但在实际的 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");
        }
    }

其他图片都是这样修改的。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...