繁体   English   中英

WPF绑定到子集合

[英]WPF Binding to a child collection

我有以下实体:

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; }
}

使用此ViewModel:

public class UserManagerViewModel : ObservableObject
{
    public ObservableCollection<Role> AllRoles { get; set; }
    public UserViewModel()
    {
        AllRoles = new ObservableCollection<Role>(RoleRepository.GetAll());
    }

    private User _selectedUser;
    public User SelectedUser
    {
        get { return _selectedUser; }
        set
        {
            if (_selectedUser != value)
            {
                _selectedUser = value;
                RaisePropertyChanged();
            }
        }
    }

    ...
}

我想以下列方式(或类似的东西)显示SelectedUser角色:

<Window.DataContext>
    <vm:UserManagerViewModel/>
</Window.DataContext>
<ListBox ItemsSource="{Binding AllRoles}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <CheckBox Content="{Binding Name}" IsChecked="{Binding ???}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
 </ListBox>

我需要设置CheckBoxIsChecked属性,以便它代表SelectedUser角色?

假设您要“检查” SelectedUser具有的角色。

首先,我们回答这个问题,“这取决于哪些数据?” 答案很简单,它取决于角色本身,所以我们写道:

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

现在显然,这不是一个博尔; 所以我们需要为它编写一个转换器来检查集合。 我们可以在这里做一个MultiValueConverter(如@ Moji的回答),但是通过Dependency Property公开集合可能更容易,并且在创建转换器时绑定。

<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;
    }
}

如果没有对此进行测试,您可能需要使用第二个返回值,因此它不会比较引用,并使用Object.Equals (或您选择的其他比较器)来确定该项是否在列表中。

您可以使用MultipleBinding和MultipleValueVonverter,如下所示

  <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();
        }
    }

暂无
暂无

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

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