2014-10-21 6 views
3

나는 다음과 같은 기관이 있습니다WPF 아이 컬렉션에 바인딩

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 역할을 표시하려면이 뷰 모델로

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 속성을 설정해야 할 것과

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

그러면 역할은 SelectedUser이됩니까?

+0

UserManagerViewModel이 샘플에 없습니다. – Maximus

+0

@ Maximus My bad, UserViewModel == UserManagerViewModel – Yoav

+0

WPF를 사용하면 데이터가 UI가 아니라 응용 프로그램이됩니다. UI는 사용자 친화적 인 데이터 반영입니다. 무언가가 선택되었는지 여부를 알아야 할 경우 데이터 모델에 해당 속성이 있어야합니다. 귀하의 경우 Role 개체에 IsSelected 속성을 추가하고 SelectedUser가 변경되면 AllRolles를 통해 선택한 사용자와 일치하도록 IsSelected 속성을 업데이트합니다. 물론 사용자가 역할을 수정하고 저장할 수 있다고 가정하면 변경 사항을 다시 'SelectedUser'에 전파 할 방법이 필요합니다. – Rachel

답변

0

당신이 SelectedUser가 가지고있는 역할 "확인"할 것을 가정

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

아래로 MultipleBinding 및 MultipleValueVonverter를 사용할 수 있습니다.

먼저 "우리는 어떤 데이터를 사용합니까?"라는 질문에 대답합니다. 대답은 매우 간단합니다. 역할 자체에 따라 달라 지므로 다음과 같이 작성합니다.

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

이제 분명히 bool이 아닙니다. 그래서 우리는 콜렉션을 검사하는 컨버터를 작성해야 할 것입니다. 우리는 (@ Moji의 답과 같이) 여기서 MultiValueConverter를 수행 할 수 있지만, 의존성 등록 정보를 통해 콜렉션을 노출하는 것이 더 쉬우 며 변환기를 생성 할 때 바인드하는 것이 더 쉽습니다.

<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 (또는 원하는 다른 비교기)를 사용할 수있다 항목이 목록에 있는지 알아 내려면

관련 문제