禁用 ToolbarItem Xamarin.Forms
Disable ToolbarItem Xamarin.Forms
我的页面中有以下内容:
<ContentPage.ToolbarItems>
<ToolbarItem Text="Run" Command="{Binding RunCommand}" />
</ContentPage.ToolbarItems>
该命令启动了一个异步任务。
只要异步任务仍在运行,我就会尝试通过将其绑定到布尔属性来禁用该控件,如下所示:
<ContentPage.ToolbarItems>
<ToolbarItem Text="Run" Command="{Binding RunCommand}" IsEnabled="{Binding MyBoolProperty}" />
</ContentPage.ToolbarItems>
我的问题是 ToolbarItem 似乎没有 "IsEnabled" 属性。有没有办法使用 Xamarin.Forms 来实现我想要做的事情?
我在这些情况下学会做的事情如下:
public Command RunCommand
{
get { return new Command(async() => await OnRunCommand()); }
}
private bool _isRunning;
public async Task OnRunCommand()
{
if (_isRunning) return;
_isRunning = true;
// do stuff
_isRunning = false;
}
缺点:这会使工具栏项目处于正常状态,用户可能会继续点击它。
好处:这将不允许同时执行 OnRunCommand 任务,这很好。
如果您想通过显示禁用图像来禁用按钮,您应该创建一个渲染器。
如果您不想在任务 运行 时显示工具栏项,请考虑从页面中删除工具栏项,稍后再重新添加。
在 William 和 Xamarin 支持的帮助下,我终于能够找到功能的工作原理。
这有点违反直觉,因为我们希望 Enable/Disable 按钮 (ToolbarItem),但实际上我们必须管理绑定到按钮的命令的状态。一旦我们理解了这种模式,它就有意义了。
ICommand 类型的 Command 对象,有一个 CanExecute 属性(感谢 William 指出)
现在你不想直接access/use它,除非它是为了实际检查命令是否可以执行。
无论您认为代码中哪里合适,要更改命令的状态,您都需要添加以下行:
((Command)_myCommand).ChangeCanExecute();
此行将强制为指定命令重新评估 CanExecute 属性。
我个人决定将它添加到我跟踪不活动的地方,因为它在我的应用程序中有意义。
public bool Inactive {
get {
return _inactive;
}
set {
if (_inactive != value) {
_inactive = value;
((Command)_myCommand).ChangeCanExecute();
OnPropertyChanged ();
}
}
}
在视图中,没有需要注意的变化:
<ToolbarItem Text="Run" Command="{Binding MyCommand}" />
现在,当您创建 Command 对象时,将完成大量工作。我们通常使用单参数构造函数,因为它通常就足够了,而且它是我们定义命令功能的地方。有趣的是,还有一个 2 参数构造函数,您可以在其中提供 function/action 来确定 CanExecute 属性.
的值
_myCommand = new Command (async () => {
Inactive = false;
await Run();
Inactive = true;
},
() => {
return Inactive;
});
public ICommand MyCommand {
get {
return _myCommand;
}
}
编辑:我知道您应该在 运行() 中从技术上更改 Inactive 的值,但出于演示目的...
这个例子是为了移除,而不是禁用,但也可能很方便。
ToolbarItem delToolbar;
...
delToolbar = new ToolbarItem
{
Order = ToolbarItemOrder.Primary,
Text = "delete",
Command = new Command(async () =>
{
ToolbarItems.Remove(delToolbar);
})
};
ToolbarItems.Add(delToolbar);
LostBalloon 的答案在使用 CanExecute
命令方面是正确的。但是我遇到的问题是 ToolbarItems
视觉状态 没有改变。我希望辅助工具栏项(即菜单项)在禁用时 变灰 (换句话说,当 CanExecute
returns 为 false 时)。一些作者说这是一个错误。可能是一个错误,但以下解决方案对我有用。
结果:
将禁用的工具栏项目变灰:
将 Resources/layout/Toolbar.xml
文件中的主题设置为 MyToolbarTheme
:
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/MyToolbarTheme"
/>
在Resources/values/styles.xml
中添加主题MyToolbarTheme
:
<style name="MyToolbarTheme" parent="ThemeOverlay.AppCompat.Light">
<item name="android:textColor">@color/menu_item_color_selector</item>
</style>
现在创建一个新文件Resources/color/menu_item_color_selector.xml
:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:color="#000"/>
<item android:color="#999"/>
</selector>
旁注:
您可以使用不同的父主题,例如,您可以使用 com.google.android.material.appbar.MaterialToolbar
而不是 androidx.appcompat.widget.Toolbar
。两种方式都有效。
一些作者参考了 actionMenuTextColor
属性来更改菜单项的字体颜色,但是这个对我不起作用(不知道为什么)。相反,我使用的是 android:textColor
并且它有效。
您可以在Toolbar.xml
中使用android:background
来设置工具栏本身的背景。
您可以通过在 MyToolbarTheme
中设置 colorControlNormal
来更改 3 个点 的颜色:
<item name="colorControlNormal">#0FF000</item>
您在 Visual Studio 中创建的任何 Android XML 资源文件必须具有构建操作 AndroidResource
并且自定义工具字段设置为 MSBuild:UpdateGeneratedFiles
(设置在属性window文件中)
除了#5,Toolbar.xml
文件必须在MainActivity.cs
中被引用:
protected override void OnCreate(Bundle bundle)
{
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
...
}
- 确保您在
Toolbar.xml
中使用 android:theme
标签,而不是 android:popupTheme
。原因不明,但 popupTheme
对我不起作用。
我的页面中有以下内容:
<ContentPage.ToolbarItems>
<ToolbarItem Text="Run" Command="{Binding RunCommand}" />
</ContentPage.ToolbarItems>
该命令启动了一个异步任务。 只要异步任务仍在运行,我就会尝试通过将其绑定到布尔属性来禁用该控件,如下所示:
<ContentPage.ToolbarItems>
<ToolbarItem Text="Run" Command="{Binding RunCommand}" IsEnabled="{Binding MyBoolProperty}" />
</ContentPage.ToolbarItems>
我的问题是 ToolbarItem 似乎没有 "IsEnabled" 属性。有没有办法使用 Xamarin.Forms 来实现我想要做的事情?
我在这些情况下学会做的事情如下:
public Command RunCommand
{
get { return new Command(async() => await OnRunCommand()); }
}
private bool _isRunning;
public async Task OnRunCommand()
{
if (_isRunning) return;
_isRunning = true;
// do stuff
_isRunning = false;
}
缺点:这会使工具栏项目处于正常状态,用户可能会继续点击它。
好处:这将不允许同时执行 OnRunCommand 任务,这很好。
如果您想通过显示禁用图像来禁用按钮,您应该创建一个渲染器。
如果您不想在任务 运行 时显示工具栏项,请考虑从页面中删除工具栏项,稍后再重新添加。
在 William 和 Xamarin 支持的帮助下,我终于能够找到功能的工作原理。
这有点违反直觉,因为我们希望 Enable/Disable 按钮 (ToolbarItem),但实际上我们必须管理绑定到按钮的命令的状态。一旦我们理解了这种模式,它就有意义了。
ICommand 类型的 Command 对象,有一个 CanExecute 属性(感谢 William 指出) 现在你不想直接access/use它,除非它是为了实际检查命令是否可以执行。
无论您认为代码中哪里合适,要更改命令的状态,您都需要添加以下行:
((Command)_myCommand).ChangeCanExecute();
此行将强制为指定命令重新评估 CanExecute 属性。
我个人决定将它添加到我跟踪不活动的地方,因为它在我的应用程序中有意义。
public bool Inactive {
get {
return _inactive;
}
set {
if (_inactive != value) {
_inactive = value;
((Command)_myCommand).ChangeCanExecute();
OnPropertyChanged ();
}
}
}
在视图中,没有需要注意的变化:
<ToolbarItem Text="Run" Command="{Binding MyCommand}" />
现在,当您创建 Command 对象时,将完成大量工作。我们通常使用单参数构造函数,因为它通常就足够了,而且它是我们定义命令功能的地方。有趣的是,还有一个 2 参数构造函数,您可以在其中提供 function/action 来确定 CanExecute 属性.
的值_myCommand = new Command (async () => {
Inactive = false;
await Run();
Inactive = true;
},
() => {
return Inactive;
});
public ICommand MyCommand {
get {
return _myCommand;
}
}
编辑:我知道您应该在 运行() 中从技术上更改 Inactive 的值,但出于演示目的...
这个例子是为了移除,而不是禁用,但也可能很方便。
ToolbarItem delToolbar;
...
delToolbar = new ToolbarItem
{
Order = ToolbarItemOrder.Primary,
Text = "delete",
Command = new Command(async () =>
{
ToolbarItems.Remove(delToolbar);
})
};
ToolbarItems.Add(delToolbar);
LostBalloon 的答案在使用 CanExecute
命令方面是正确的。但是我遇到的问题是 ToolbarItems
视觉状态 没有改变。我希望辅助工具栏项(即菜单项)在禁用时 变灰 (换句话说,当 CanExecute
returns 为 false 时)。一些作者说这是一个错误。可能是一个错误,但以下解决方案对我有用。
结果:
将禁用的工具栏项目变灰:
将 Resources/layout/Toolbar.xml
文件中的主题设置为 MyToolbarTheme
:
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/MyToolbarTheme"
/>
在Resources/values/styles.xml
中添加主题MyToolbarTheme
:
<style name="MyToolbarTheme" parent="ThemeOverlay.AppCompat.Light">
<item name="android:textColor">@color/menu_item_color_selector</item>
</style>
现在创建一个新文件Resources/color/menu_item_color_selector.xml
:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:color="#000"/>
<item android:color="#999"/>
</selector>
旁注:
您可以使用不同的父主题,例如,您可以使用
com.google.android.material.appbar.MaterialToolbar
而不是androidx.appcompat.widget.Toolbar
。两种方式都有效。一些作者参考了
actionMenuTextColor
属性来更改菜单项的字体颜色,但是这个对我不起作用(不知道为什么)。相反,我使用的是android:textColor
并且它有效。您可以在
Toolbar.xml
中使用android:background
来设置工具栏本身的背景。您可以通过在
MyToolbarTheme
中设置colorControlNormal
来更改 3 个点 的颜色:
<item name="colorControlNormal">#0FF000</item>
您在 Visual Studio 中创建的任何 Android XML 资源文件必须具有构建操作
AndroidResource
并且自定义工具字段设置为MSBuild:UpdateGeneratedFiles
(设置在属性window文件中)除了#5,
Toolbar.xml
文件必须在MainActivity.cs
中被引用:
protected override void OnCreate(Bundle bundle)
{
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
...
}
- 确保您在
Toolbar.xml
中使用android:theme
标签,而不是android:popupTheme
。原因不明,但popupTheme
对我不起作用。