繁体   English   中英

禁用 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 实现我想要做的事情?

在 William 和 Xamarin 支持的帮助下,我终于能够找到功能的工作原理。

这有点违反直觉,因为我们期望启用/禁用按钮 (ToolbarItem),但我们实际上必须管理绑定到按钮的命令的状态。 一旦我们理解了这种模式,它就有意义了。

ICommand 类型的 Command 对象有一个 CanExecute 属性(感谢 William 指出)现在您不想直接访问/使用它,除非它实际检查命令是否可以执行。

无论您在代码中认为合适的位置,要更改命令的状态,您都需要添加以下行:

((Command)_myCommand).ChangeCanExecute();

此行将强制为指定的命令重新评估 CanExecute 属性。

我个人决定将它添加到我跟踪不活动的地方,因为它在我的应用程序中是有意义的。

public bool Inactive { 
    get { 
        return _inactive;
    } 
    set {
        if (_inactive != value) {
            _inactive = value;
            ((Command)_myCommand).ChangeCanExecute();
            OnPropertyChanged ();
        }
    }
}

在View中,没有需要注意的变化:

<ToolbarItem Text="Run" Command="{Binding MyCommand}" />

现在,当您创建 Command 对象时,将完成大量工作。 我们通常使用单参数构造函数,因为它通常就足够了,它是我们定义命令做什么的地方。 有趣的是,还有一个 2 参数构造函数,您可以在其中提供确定 CanExecute 属性值的函数/操作。

_myCommand = new Command (async () => {
                                          Inactive = false;
                                          await Run();
                                          Inactive = true;
                                      },
                                      () => {
                                          return Inactive;
                                      });


public ICommand MyCommand {
    get { 
        return _myCommand;
    }
}

编辑:我知道您应该在 Run() 中从技术上更改 Inactive 的值,但出于演示目的...

这个例子是删除,而不是禁用,但也可能很方便。

    ToolbarItem delToolbar;       

    ...

        delToolbar = new ToolbarItem
        {
            Order = ToolbarItemOrder.Primary,                
            Text = "delete",              
            Command = new Command(async () =>
            {                                       
                ToolbarItems.Remove(delToolbar);
            })
        };
        ToolbarItems.Add(delToolbar);

我在这些情况下学到的做法如下:

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 任务,这很好。

如果您想通过显示禁用的图像来禁用按钮,您应该创建一个渲染器。

如果您不想在任务运行时显示工具栏项目,请考虑从页面中删除工具栏项目并稍后重新添加。

LostBalloon 的答案在使用CanExecute命令方面是正确的。 但我面临的问题是ToolbarItems视觉状态没有改变。 我想第二栏项目(即菜单项)变灰禁用时(换句话说,当CanExecute返回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>

旁注:

  1. 您可以使用不同的父主题,例如,您可以使用com.google.android.material.appbar.MaterialToolbar代替androidx.appcompat.widget.Toolbar 无论哪种方式都有效。

  2. 一些作者参考属性actionMenuTextColor来更改菜单项字体颜色,但这个对我不起作用(不知道为什么)。 相反,我使用的是android:textColor并且它有效。

  3. 您可以使用Toolbar.xml android:background来设置工具栏本身的背景。

  4. 您可以通过在MyToolbarTheme设置colorControlNormal来更改3 个点的颜色:

<item name="colorControlNormal">#0FF000</item>
  1. 您在 Visual Studio 中创建的任何 Android XML 资源文件,必须将构建操作AndroidResource和自定义工具字段设置为MSBuild:UpdateGeneratedFiles (将其设置在文件的属性窗口中)

  2. 除了 #5 之外,必须在MainActivity.cs引用Toolbar.xml文件:

protected override void OnCreate(Bundle bundle)
{
    ToolbarResource = Resource.Layout.Toolbar;
    base.OnCreate(bundle);
    ...
}
  1. 确保您在Toolbar.xml中使用android:theme标签,而不是android:popupTheme 不知道为什么,但是popupTheme对我不起作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM