내용 보기

작성자

관리자 (IP : 172.17.0.1)

날짜

2020-07-10 03:11

제목

[WPF] 한개의 ItemSource를 사용하여 여러개 View 바인딩하여 표시하기 - 필터 적용


one ItemsSource, multiple views, multiple filters

한개의 ItemSource를 사용해서 여러개의 View에 표시를 해야 할 상황이 있다.
가령 원본 ItemSource가 변경 될때 자동으로 그에 따른 View들도 같이 반영 되어야 하는 경우가 대표 적이다.
이럴경우 ICollectionView 를 사용하여 처리 할 수 있다.
다음은 예제 코드이다.

XAML

<ListView x:Name="xInternalFileTypeList" Grid.Row="1" SelectionMode="Single"ItemsSource="{Binding InternalFileTypeList}">
  <ListView.ItemTemplate>
    <DataTemplate>
      <Grid>
        <TextBlock Text="{Binding FileType}" />
      </Grid>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>
 
<ListView x:Name="xInternalAcceptFileTypeList" Grid.Row="1" SelectionMode="Single"ItemsSource="{Binding InternalAcceptFileTypeList}">
<ListView.ItemTemplate>
    <DataTemplate>
      <Grid>
        <TextBlock Text="{Binding FileType}" />
      </Grid>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>
cs

위 처럼 각각의 ListView 컨트롤을 놓고 원본 ItemSource 하나를 필터 적용하여 표시할려고 한다.

ViewModel.cs

#region Member Fields
// 원본 ItemSource
private ObservableCollection<FileTypeModel> _fileTypeList = new ObservableCollection<FileTypeModel>();
private ICollectionView _internalFileTypeList;
private ICollectionView _internalAcceptFileTypeList;
#endregion  // Member Fields
 
#region Construct
public TransferPolicyViewModel()
{
    // For Test
    // 가라 데이터
    FileTypeModel fileType1 = new FileTypeModel()
    {
        FileType = "exe",
        Description = "설명1",
        UseInternal = true
    };
    FileTypeModel fileType2 = new FileTypeModel()
    {
        FileType = "jpg",
        Description = "설명2",
        UseExternal = true
    };
    FileTypeModel fileType3 = new FileTypeModel()
    {
        FileType = "gif",
        Description = "설명3",
        UseInternal = true,
        UseExternal = true
    };
 
    // 모든 파일 유형 List
    FileTypeList.Add(fileType1);
    FileTypeList.Add(fileType2);
    FileTypeList.Add(fileType3);
 
    // For Test End
    InternalFileTypeList = this.GetFileTypeListByInternalFilter(FileTypeList, false);
    InternalAcceptFileTypeList = this.GetFileTypeListByInternalFilter(FileTypeList, true);
}
#endregion  // // Construct
 
 
#region Properties
public ObservableCollection<FileTypeModel> FileTypeList
{
    get
    {
        return _fileTypeList;
    }
    set
    {
        _fileTypeList = value;
        this.OnPropertyChanged("FileTypeList");
    }
}
 
public ICollectionView InternalFileTypeList
{
    get
    {
        return _internalFileTypeList;
    }
    set
    {
        _internalFileTypeList = value;
        this.OnPropertyChanged("InternalFileTypeList");
    }
}
 
public ICollectionView InternalAcceptFileTypeList
{
    get
    {
        return _internalAcceptFileTypeList;
    }
    set
    {
        _internalAcceptFileTypeList = value;
        this.OnPropertyChanged("InternalAcceptFileTypeList");
    }
}
#endregion  // Properties
 
 
#region Methods
private ICollectionView GetFileTypeListByInternalFilter(ObservableCollection<FileTypeModel> source, bool isUse)
{
CollectionViewSource cvs = new CollectionViewSource();
        cvs.Source = source;
        if (cvs.View.CanFilter)
        {
                 cvs.View.Filter = ((p) =>
{
                       FileTypeModel fileType = p as FileTypeModel;
                       if(fileType.UseInternal == isUse)
                       {
                            return true;
                       }
                       else
                       {
                            return false;
                       }
});
         }
 
         return cvs.View;
}
 
private ICollectionView GetFileTypeListByExternalFilter(ObservableCollection<FileTypeModel> source, bool isUse)
{
CollectionViewSource cvs = new CollectionViewSource();
        cvs.Source = source;
        if (cvs.View.CanFilter)
        {
                 cvs.View.Filter = ((p) =>
{
                       FileTypeModel fileType = p as FileTypeModel;
                       if(fileType.UseExternal == isUse)
                       {
                            return true;
                       }
                       else
                       {
                            return false;
                       }
});
         }
 
         return cvs.View;
}
#endregion  // Methods
cs

코드에서 처럼 CollectionViewSourceFilter를 사용하여 ObservableCollection<T>타입의 ItemSource에 Filter처리를 하여 View를 얻어 낼 수 있다.
Filter가 적용된 View는 CollectionViewSourceView 속성으로 ICollectionView타입을 얻을 수 있으며 이것을 바인딩 하여 컨트롤에 표시 할 수 있다.

출처1

출처2