[英]How to temporarily disable button after click in Xamarin Forms?
I am making a poll application in Xamarin Forms
and I want users to be able to vote just one time/day.我正在
Xamarin Forms
中进行投票申请,我希望用户每天只能投票一次。 On the UI page, I created an ImageButton and I want the user to be able to click it just one time/day.在 UI 页面上,我创建了一个 ImageButton,我希望用户能够每天点击一次。 I tried using a Timer, and tried to test it for 5 seconds intervals.
我尝试使用计时器,并尝试以 5 秒的间隔对其进行测试。 The Application disabled the button when I first clicked it but after 5 seconds I could click it all over again and it doesn't disable the button.
应用程序在我第一次单击它时禁用了该按钮,但 5 秒后我可以再次单击它并且它不会禁用该按钮。
private void ImageButton_Clicked(object sender, EventArgs e)
{
this.IsEnabled = false;
Timer aTimer = new Timer();
aTimer.Interval = 5000; //ms
aTimer.Enabled = true;
aTimer.Elapsed += ATimer_Elapsed;
}
private void ATimer_Elapsed(object sender, ElapsedEventArgs e)
{
this.IsEnabled = true;
}
I saw that the application enters the ImageButton_Clicked
function all the time but it does not execute this.IsEnabled=false
;我看到应用程序一直输入
ImageButton_Clicked
function 但它没有执行this.IsEnabled=false
;
Try this code.试试这个代码。 I hope it is working.
我希望它正在工作。
private void ImageButton_Clicked(object sender, EventArgs e)
{
var btn = sender as ImageButton;
btn.IsEnabled = false;
Device.StartTimer(TimeSpan.FromSeconds(5), () =>
{
btn.IsEnabled = true;
return false;
});
}
Actually, the application is doing what you have told it.实际上,该应用程序正在执行您告诉它的操作。
this.IsEnabled
is working, but this is referencing the page itself. this.IsEnabled
正在工作,但这是引用页面本身。 If you want on click to disable the button that has fired event, then you need this:如果要单击以禁用已触发事件的按钮,则需要:
private void ImageButton_Clicked(object sender, EventArgs e)
{
if (sender is Button button)
{
button.IsEnabled = false;
// the rest of the logic
}
}
Here, we are casting the sender
as a Xamarin.Forms.在这里,我们将
sender
转换为 Xamarin.Forms。 Button .按钮。 If the cast is successful, meaning if the sender is our button, then we can disable it.
如果转换成功,这意味着如果发送者是我们的按钮,那么我们可以禁用它。
If you don't want to cast it or you want do use the button reference in another method (like you are enabling it again), the simply set the button with a Name
property in the xml like so:如果您不想转换它或者您想在另一种方法中使用按钮引用(就像您再次启用它一样),只需在 xml 中使用
Name
属性设置按钮,如下所示:
<Button
x:Name="myButton"
Clicked="ImageButton_Clicked" />
Then, you can use it in the code-behind in the ATimer_Elapsed
method like this:然后,您可以在
ATimer_Elapsed
方法的代码隐藏中使用它,如下所示:
private void ATimer_Elapsed(object sender, ElapsedEventArgs e)
{
Device.BeginInvokeOnMainThread(() => { myButton.IsEnabled = true; });
}
Edit: It is very important to invoke the IsEnabled = true
here on the main/UI thread, since the timer logic is being done on a background thread.编辑:在主/UI线程上调用
IsEnabled = true
非常重要,因为计时器逻辑是在后台线程上完成的。
The answer for this question is a bit long, but simple.这个问题的答案有点长,但很简单。
Create a custom button component because XF doesn't disable button and change the color properly (at least for me):创建一个自定义按钮组件,因为 XF 不会禁用按钮并正确更改颜色(至少对我而言):
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="LindeGctMobileApplication.Modules.CustomComponents.CustomButton.CustomButtonView"
FontAttributes="Bold"
TextColor="{StaticResource LightTextPrimary}"
FontSize="20"
TextTransform="Uppercase"
CornerRadius="20"
WidthRequest="200"
HorizontalOptions="Center" />
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CustomButtonView
{
#region constructors
public CustomButtonView()
{
InitializeComponent();
BackgroundColor = Color.Blue;
Clicked += (_, args) =>
{
if (IsEnabled) Command?.Execute(args);
};
}
#endregion
#region Command
public new static readonly BindableProperty CommandProperty = BindableProperty.Create(
nameof(Command),
typeof(ICommand),
typeof(CustomButtonView));
public new ICommand? Command
{
get => (ICommand)GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
#endregion
#region IsEnabled
public new static readonly BindableProperty IsEnabledProperty = BindableProperty.Create(
nameof(IsEnabled),
typeof(bool),
typeof(CustomButtonView),
true,
propertyChanged: (bindable, _, newValue) =>
{
var component = (CustomButtonView)bindable;
if ((bool)newValue)
{
component.BackgroundColor = Color.Blue;
}
else
{
component.BackgroundColor = Color.Gray;
}
});
public new bool IsEnabled
{
get => (bool)GetValue(IsEnabledProperty);
set => SetValue(IsEnabledProperty, value);
}
#endregion
}
<customButton:CustomButtonView Text="Your Custom Button"
Command="{Binding ClickCommand}"
IsEnabled="{Binding IsEnabled}"/>
public static class CustomTaskExtension
{
#region fields
private static int _last;
#endregion
public static void Debounce(CancellationTokenSource throttleCts, double debounceTimeMs, Action action)
{
var current = Interlocked.Increment(ref _last);
Task.Delay(TimeSpan.FromMilliseconds(debounceTimeMs), throttleCts.Token).ContinueWith(task =>
{
if (current == _last) action();
task.Dispose();
});
}
}
private bool _isEnabled;
public bool IsEnabled
{
get => _isEnabled;
set
{
OnPropertyChanged("IsEnabled");
_isEnabled = value;
}
}
public ICommand ClickCommand => new Command(() => Click());
private void Click()
{
// disable the button
IsEnabled = false;
// the debounce is used to enable the button after 5s of the last call of this method
CustomTaskExtension.Debounce(new CancellationTokenSource(), 5000, () =>
{
IsEnabled = true;
});
}
That's all Folks!这就是所有的人!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.