您忘记定义“滑动”。Winforms 没有手指输入的概念,只有鼠标拖动的概念。
如果操作员向左拖动鼠标,图像随之移动,您是否想要?一个小的拖动是否足够,或者操作员应该将图像完全拖动到窗口之外?
如果操作员拖动一小部分,但停止拖动,会发生什么情况?图像是否应该像没有阻力一样向后移动?还是应该将图像拖到一半?
模型
您使用了图像这个词,但实际上图像代表更多的东西:在 Tinder 中,它代表图像背后的人、姓名、出生日期、描述和其他部分,其中包括图像。
让我们称之为 a Profile
:每个配置文件都有几个属性,其中包括一个 Image。
class Profile
{
public Image Image {get; set;}
...
}
在您的模型中,您将需要一个“要显示的配置文件”的 FIFO 序列、一组被拒绝的配置文件和一组接受的配置文件。你没有说你想对被拒绝和接受的配置文件做什么,所以我所做的只是将被拒绝的配置文件放在一个存储库中,将接受的配置文件放在不同的存储库中。
存储库中发生的事情对于模型是隐藏的。可能是您删除了所有内容,或者将其保存在文件、数据库或其他任何东西中,您的模型不必知道。它所需要知道的是,两个存储库都需要有一个接口来放入配置文件:
interface IProfileRepository
{
void Add (Profile profile);
}
包含被拒绝图像的存储库可能只是将配置文件丢弃,而其他存储库可能会执行诸如通知配置文件所有者他已被接受之类的事情。
我们还需要一些输入配置文件。我也不知道他们来自哪里:
interface IProfileSource
{
Profile GetProfile(); // returns the next Profile
}
实际的 ProfileSource 可能会从 XML 文件、互联网或其他任何地方读取数据,这不在问题范围内。
因此,在您的程序中,您将拥有以下内容:
class ProfileModel
{
private IProfileSource ProfileSource {get;} = new ...;
private IProfileRepository AcceptedProfiles {get;} = new ...;
private IProfileRepository RejectedProfiles {get;} = new ...;
public Profile GetNextProfile()
{
return ProfileSource.GetProfile();
}
public void AcceptProfile(Profile profile)
{
AcceptedProfiles.Add(profile);
}
public void RejectProfile(Profile profile)
{
RejectedProfiles.Add(profile);
}
看法
显示配置文件图像的表单将需要一个显示配置文件的用户控件。它隐藏了配置文件的显示内容。您可能只会显示图像,但如果需要,您可以让它显示人的年龄,或姓名、位置等。您的程序所知道的就是您可以要求 ProfileControl 显示个人资料,什么是否显示以及如何显示取决于 ProfileControl。
使用 Visual Studio 创建一个名为 ProfileControl 的新 UserControl。使用 Visual Studio 设计器在需要显示配置文件时在控件上绘制要显示的内容。如果您只想显示图像,请将 PictureBox 添加到 ProfileControl 并让它停靠。如果您还想显示名称,请添加标签等
class ProfileControl : UserControl
{
private Profile profile;
public ProfileControl()
{
InitializeComponents();
}
public Profile Profile
{
get => this.profile;
set
{
if (this.Profile != value)
{
this.profile = value;
this.pictureBox1.Image = this.profile.Image;
}
}
}
}
考虑添加一个事件 ProfileChanged 和一个受保护的方法 OnProfileChanged,以通知其他人此 ProfileControl 显示一个新图像。
您将需要另一个 UserControl 来执行 ProfileControl 的拖动。它将有两个 ProfileControl:当前一个和下一个。在 MouseDrag 时,当前 ProfileControl 的位置和下一个 ProfileControl 将改变。下一个 ProfileControl 将与当前的 ProfileControl 相邻,具体取决于拖动的方向。
这SwipeControl
隐藏了滑动是如何完成的。SwipeControl(= 软件,而不是操作员)的用户只会设置当前和下一个配置文件,并且只要当前配置文件通过事件被接受或拒绝,它就会收到通知。该事件将自动设置下一个配置文件(如果有的话)
使用 Visual Studio 设计器为 SwipeControl 提供两个 ProfileControl。为事件添加事件处理程序:
- MouseDown:将当前鼠标位置记住为
DragStartPosition
. 为 CurrentProfileControl 和 NextProfileControl 指定 SwipeControl 的 ClientArea 的大小。将 CurrentProfileControl 的 Location 设置为 (0, 0),因此它位于 SwipeControl 的 ClientArea 的左上角。NextProfileControl 仍然不可见,我们不知道操作员是向左滑动还是向右滑动。
- MouseMove:鼠标移动的水平距离 = 当前鼠标位置 X - DragStartPosition X。移动 X 位置 CurrentProfileControl 与此移动距离。决定 NextProfileControl 应该位于 CurrentProfileControl 的左侧还是右侧。计算位置。使 NextProfileControl 可见。
- MouseUp:如果距离已超过某个最小值,则将滑动设置为完成,否则撤消:停靠当前并使下一个不可见。
SwipeComplete:如果接受,则引发事件 ProfileAccepted,如果被拒绝,则引发事件 ProfileRejected。NextProfileControl 中的 Profile 设置为 CurrentProfileControl。获取 NextProfile 并将其放入 NextProfileControl
class SwipeControl : CustomControl
{
public Profile CurrentProfile
{
get => this.CurrentProfileControl.Profile;
set => this.CurrentProfileControl.Profile = value;
}
public Profile NextProfile
{
get => this.NextProfileControl.Profile;
set => this.NextProfileControl.Profile = value;
}
public event EventHandler ProfileAccepted;
public event EventHandler ProfileRejected;
protected virtual void OnProfileAccepted()
{
// raise event ProfileAccepted
this.ProfileAccepted?.Invoke(this, EventArgs.Empty);
}
使用 Visual Studio 设计器添加事件处理程序并按照编写的方式实现代码。
##SwipeForm##
使用 Visual Studio 设计器将 SwipeControl 添加到 SwipeForm。还要添加模型。
订阅 SwipeControl 的 Accepted / Rejected 事件。
加载表单后:从模型中获取第一个和下一个 Profile 并将它们放入 SwipeControl
事件 ProfileAccepted:从 SwipeControl 获取 CurrentProfile 并将其作为 Accepted 放入模型中。nextProfile 将是当前的。从模型中获取下一个并将其设置为 SwipeControl 中的下一个配置文件。
对事件 ProfileRejected 做类似的事情