Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF绑定到子集合_C#_Wpf_Binding - Fatal编程技术网

C# WPF绑定到子集合

C# WPF绑定到子集合,c#,wpf,binding,C#,Wpf,Binding,我拥有以下实体: public class User { public User() { Roles = new ObservableCollection<Role>(); } public int UserId { get; set; } public string Name { get; set; } public DateTime DateOfBirth { get; set; } public vir

我拥有以下实体:

public class User
{
    public User()
    {
        Roles = new ObservableCollection<Role>();
    }

    public int UserId { get; set; }
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }

    public virtual ICollection<Role> Roles { get; set; }
}

public class Role
{
    public int RoleId { get; set; }
    public string Name { get; set; }

    public virtual User User { get; set; }
}

我需要设置
复选框的
IsChecked
属性,以便它代表
SelectedUser
角色,这需要做什么?

您可以使用如下所示的MultipleBinding和MultipleValueInverter

  <Grid>
        <Grid.Resources>
            <local:RoleValueConverter x:Key="converter"></local:RoleValueConverter>
        </Grid.Resources>
        <ListBox ItemsSource="{Binding AllRoles}" >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <CheckBox Content="{Binding Name}" >
                        <CheckBox.IsChecked>
                            <MultiBinding Converter="{StaticResource converter}">
                                <Binding Path="."></Binding>
                                <Binding  RelativeSource="{RelativeSource AncestorType={x:Type ListBox}}"  Path="DataContext"></Binding>
                            </MultiBinding>
                        </CheckBox.IsChecked>
                    </CheckBox>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
 public class RoleValueConverter : IMultiValueConverter
    {

        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
           //values[0] is Role object
    //value[1] is UserManagerViewModel 
   // then you can see if Selected user had Role object return true else return false 
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

公共类RoleValueConverter:IMultiValueConverter
{
公共对象转换(对象[]值,类型targetType,对象参数,System.Globalization.CultureInfo区域性)
{
//值[0]是角色对象
//值[1]是UserManagerViewModel
//然后,您可以查看所选用户的角色对象是否返回true,否则返回false
}
公共对象[]转换回(对象值,类型[]目标类型,对象参数,System.Globalization.CultureInfo区域性)
{
抛出新的NotImplementedException();
}
}
假设您希望“检查”所选用户的角色

首先我们回答这个问题,“这取决于什么数据?”答案很简单,取决于角色本身,因此我们写道:

<CheckBox Content="{Binding Name}" IsChecked="{Binding .}"/>

现在很明显,这不是一个错误;因此,我们需要为它编写一个转换器来检查集合。我们可以在这里做一个多值转换器(如@Moji的回答),但是通过依赖属性公开集合,并在创建转换器时绑定可能更容易

<Window.Resources>
   <local:CollectionContainsConverter Collection="{Binding SelectedUser.Roles}"/>
</Window.Resources>

<CheckBox Content="{Binding Name}" IsChecked="{Binding Path=., Converter={StaticResource CollectionContainsConverter}"/>

和转换器:

public class CollectionContainsConverter : IValueConverter
{
    public IEnumerable<object> Collection { get; set; } //This is actually a DP

    public object Convert(...)
    {
        return Collection.Contains(value);
        // or possibly, to allow for the Object.Equals override
        return Collection.Any(o => o.Equals(value));
    }

    public object ConvertBack(...)
    {
         return Binding.DoNothing;
    }
}
公共类集合包含转换器:IValueConverter
{
公共IEnumerable集合{get;set;}//这实际上是一个DP
公共对象转换(…)
{
返回集合。包含(值);
//或者,允许对象。等于覆盖
返回集合.Any(o=>o.Equals(value));
}
公共对象转换回(…)
{
不做任何事;
}
}

尚未测试此项,您可能需要使用第二个返回,以便它不会比较引用,并利用
Object.Equals
(或您选择的另一个比较器)确定该项是否在列表中。

示例中缺少UserManagerViewModel。@Maximus My bad,UserViewModel==UserManagerViewModelWith WPF,您的数据是您的应用程序,而不是UI。UI只是数据的一个非常用户友好的反映。如果您需要知道是否选择了某个对象,那么应该在数据模型上具有该属性。在您的情况下,我会向您的角色对象添加一个IsSelected属性,当SelectedUser发生更改时,我会遍历AllRolles并更新IsSelected属性以匹配所选用户。当然,假设用户可以修改和保存角色,您需要某种方式将其更改传播回
SelectedUser
too@Rachel我同意你建议的方法,目前正在努力实施。由于
User
Role
是由
Entity Framework
生成的实体,我更喜欢创建一个
RoleViewModel
,它将保存角色名和一个
IsChecked
属性。@Yoav yes,我同意这个决定:)我本来打算把它包括进去,但是它不适合评论,我不得不花时间写一个答案。我想我可能在某一点上有一个类,它可以简单地向现有对象添加一个IsSelected或IsChecked值,因为这种事情对我来说相当常见。。。不过我现在记不起来了。我想说的是,它的用法类似于
ObservableCollection
,但我不记得了。
<Window.Resources>
   <local:CollectionContainsConverter Collection="{Binding SelectedUser.Roles}"/>
</Window.Resources>

<CheckBox Content="{Binding Name}" IsChecked="{Binding Path=., Converter={StaticResource CollectionContainsConverter}"/>
public class CollectionContainsConverter : IValueConverter
{
    public IEnumerable<object> Collection { get; set; } //This is actually a DP

    public object Convert(...)
    {
        return Collection.Contains(value);
        // or possibly, to allow for the Object.Equals override
        return Collection.Any(o => o.Equals(value));
    }

    public object ConvertBack(...)
    {
         return Binding.DoNothing;
    }
}