首页 > 解决方案 > 是否可以将 MenuItem.IsEnabled 属性绑定到不同的上下文?

问题描述

我有一个ListView绑定到一组对象(在这种情况下称为User s),并且模板包含一个ContextActions菜单。需要根据与视图中的项目没有直接关系的条件来启用或禁用其中一个菜单项(无论是否存在与某种外围设备的蓝牙连接)。我现在正在做的是迭代TemplatedItems属性中的 Cell 并在每个上设置IsEnabled

这是ListView的 XAML ,精简到对我的问题很重要的部分:

<ListView ItemsSource="{Binding .}" ItemTapped="item_Tap">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextCell Text="{Binding Label}">
                <TextCell.ContextActions>
                    <MenuItem
                        Text="Copy to other device"
                        ClassId="copyMenuItem"
                        Clicked="copyMenuItem_Click" />
                </TextCell.ContextActions>
            </TextCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

这是我现在设置属性值的方式:

foreach (Cell cell in usersListView.TemplatedItems)
{
    foreach (MenuItem item in cell.ContextActions)
    {
        if ("copyMenuItem" == item.ClassId)
        {
            item.IsEnabled = isBluetoothConnected;
        }
    }
}

这行得通,但我不喜欢它。这显然与数据绑定视图的整体理念不符。我宁愿有一个可以绑定到IsEnabled属性的布尔值,但是从对象设计的角度来看,将它添加到User对象没有意义;它与该类的内容(代表登录帐户)无关。我想将User包装在某个存在的本地类中,只是为了将这个布尔属性粘贴到它上面,但这也感觉很奇怪,因为集合中的每个项目的值总是相同的。还有其他方法可以绑定MenuItem.IsEnabled属性吗?

标签: c#xamlxamarin.formsxaml-binding

解决方案


使用相对绑定

  1. 在您的视图模型类、继承INotifyPropertyChanged或您的BaseViewModel.
    public class YourViewModel : INotifyPropertyChanged
    {
        private string isBluetoothConnected;

        public string IsBluetoothConnected
        {
            get => isBluetoothConnected;
            set => SetProperty(ref isBluetoothConnected, value);
        }

        public ObservableCollection<User> Users { get; private set; }
    }
  1. 为 ListView 添加名称以供参考,并在 MenuItem 中应用相对绑定。
<ListView
    x:Name="UserListView"
    ItemsSource="{Binding Users}"
    ItemTapped="item_Tap">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextCell Text="{Binding Label}">
                <TextCell.ContextActions>
                    <MenuItem
                        IsEnabled="{Binding Path=BindingContext.IsBluetoothConnected, Source={x:Reference UserListView}}"
                        Text="Copy to other device"
                        ClassId="copyMenuItem"
                        Clicked="copyMenuItem_Click" />
                </TextCell.ContextActions>
            </TextCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

推荐阅读