C# 如果值存在于其他列表中,则IsEnabled

C# 如果值存在于其他列表中,则IsEnabled,c#,wpf,C#,Wpf,如果我的其他列表中不存在值,我很难理解如何禁用TextBox。 我有两个列表(用户和管理员)。我正在ListView中显示一个用户列表,其中我拥有所有用户,如果给定的用户/项目不存在于另一个列表中(我的列表:Admins),我想将属性IsEnabled设置为false) 在XAML中,我得到了: <ListView ItemsSource="{Binding Users}" x:Name="myListViewExample"> <

如果我的其他列表中不存在值,我很难理解如何禁用
TextBox
。 我有两个列表(
用户
管理员
)。我正在
ListView
中显示一个用户列表,其中我拥有所有用户,如果给定的用户/项目不存在于另一个列表中(我的列表:
Admins
),我想将属性
IsEnabled
设置为
false

在XAML中,我得到了:

<ListView ItemsSource="{Binding Users}" x:Name="myListViewExample">
   <ListView.View>
      <GridView>
         <GridViewColumn Header="name">
            <GridViewColumn.CellTemplate>
               <DataTemplate>
                  <TextBox d:DataContext="d:DesignInstance {x:Type model:User}}" Text="{Binding name, Mode=TwoWay, NotifyOnValidationError=true}"/>
               </DataTemplate>
            </GridViewColumn.CellTemplate>
         </GridViewColumn>
         <GridViewColumn Header="login">
            ´<GridViewColumn.CellTemplate>
               <DataTemplate>
                  <TextBox d:DataContext="d:DesignInstance {x:Type model:User}}" Text="{Binding login, Mode=TwoWay, NotifyOnValidationError=true}" IsEnabled="{Binding ???}"/>
               </DataTemplate>
            </GridViewColumn.CellTemplate>
         </GridViewColumn>
         <!--...other columns-->
         <GridView>
   </ListView.View>
</ListView>

´
在模型中:

private List<User> admins;
public List<User> Admins
{
    get { return admins; }
    set {
        admins = value;
        RaisePropertyChanged(() => Admins);
    }
}
私有列表管理员;
公共列表管理员
{
获取{返回管理员;}
设置{
管理员=价值;
RaisePropertyChanged(()=>Admins);
}
}

无论是
用户
还是
管理员
都有一个共同点,那就是他们的列表中都有
用户
类型的项目,这似乎是多余的,因为作为管理员应该是
用户
的属性。复制在这里似乎很奇怪

假设您将属性
isAdmin
添加到
User
模型中,或者使用这样的属性创建一个单独的包装器模型来消除您的问题

public class User
{
   // ...other fields, methods or properties.

   public string name { get; set; }

   public string login { get; set; }

   public bool isAdmin { get; set; }
}
然后,您可以简单地将
IsEnabled
绑定到
isAdmin
属性

<TextBox d:DataContext="d:DesignInstance {x:Type model:User}}" Text="{Binding login, Mode=ToWay, NotifyOnValidationError=true}" IsEnabled="{Binding isAdmin}"/>

由于您特别要求提供转换器,我将提供一个作为概念证明,但我不建议这样做,因为它效率低下,而且有更好的替代方案,请参见上文

您可以创建一个多值转换器,它接受两个绑定值,第一个是具体的
User
,第二个是
IEnumerable
。它将检查用户是否包含在集合中。我在这里比较了两个用户的
名称
,因为我猜它是唯一的,我不知道您是否在
用户
类型中实现了相等运算符,或者
用户
管理员
是否都包含相同的
用户
实例,如果您要比较引用,则需要这些实例。请根据您的需要进行调整

public class ContainsUserConverter : IMultiValueConverter
{
   public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
   {
      if (values == null || values.Length != 2 || !(values[0] is User user) || !(values[1] is IEnumerable<User> users))
         throw new ArgumentException("The provided values are invalid.");

      return users.Any(u => u.name == user.name);
   }

   public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
   {
      throw new InvalidOperationException("This conversion is invalid.");
   }
}

用户
管理员
列表是否相互独立更改?如果我从用户列表中删除项,我将从列表管理员中删除同一用户。我无法在用户类中添加属性,因为它来自其他应用程序的json。我必须始终如一。我的列表管理员总是很小,我需要两个列表。@您是否可以添加一个包装类,例如带有属性
IsAdmin
UserViewModel
,并使用该类来代替?在内部,它可以只使用
用户
类。如果这样更好,那么我想是的,但可能有一些转换器?@jrJerry我已经为这两个添加了示例,但我不推荐值转换器。非常感谢。
public class ContainsUserConverter : IMultiValueConverter
{
   public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
   {
      if (values == null || values.Length != 2 || !(values[0] is User user) || !(values[1] is IEnumerable<User> users))
         throw new ArgumentException("The provided values are invalid.");

      return users.Any(u => u.name == user.name);
   }

   public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
   {
      throw new InvalidOperationException("This conversion is invalid.");
   }
}
<ListView ItemsSource="{Binding Users}" x:Name="myListViewExample">
   <ListView.Resources>
      <local:ContainsUserConverter x:Key="ContainsUserConverter"/>
   </ListView.Resources>
   <ListView.View>
      <GridView>
         
         <!-- ...other columns. -->

         <GridViewColumn Header="login">
            <GridViewColumn.CellTemplate>
               <DataTemplate>
                  <TextBox Text="{Binding login, Mode=TwoWay, NotifyOnValidationError=true}">
                     <TextBox.IsEnabled>
                        <MultiBinding Converter="{StaticResource ContainsUserConverter}">
                           <Binding/>
                           <Binding Path="DataContext.Admins" RelativeSource="{RelativeSource AncestorType={x:Type ListView}}"/>
                        </MultiBinding>
                     </TextBox.IsEnabled>
                  </TextBox>
               </DataTemplate>
            </GridViewColumn.CellTemplate>
         </GridViewColumn>
      </GridView>

      <!-- ...other columns. -->

   </ListView.View>
</ListView>