ListView 기본 (3)

ListView의 셀의 표현은 두가지 방법으로 접근할 수 있다.

  • 기본셀 커스터마이징 - 비용면에서 저렴하고 쉽게 구현이 가능하다.
  • 커스텀셀 생성 - 좀 더 정교한 결과물을 만들어 낼 수 있다. 하지만, 재대로 구현하지 못할 경우 성능 이슈를 야기할 수 있다.

기본 셀

간단한 어플리케이션들을 위해 기본적인 셀을 포함하고 있다.

  • TextCell - 텍스트를 표현하기 위한 셀
  • ImageCell - 이미지와 텍스트를 표현하기 위한 셀

SwitchCellEntryCell도 제공되고 있지만, 이들은 ListView보다는 TableView에 주로 사용된다.

TextCell

TextCell은 텍스트를 표현하며, 옵션으로 두번째 줄에 상세 텍스트를 표현할 수 있다.
TextCell은 네이티브 컨트롤을 실행하여 성능이 커스텀셀에 비해 뛰어나다. TextCell은 다음 속성들을 지원한다.

  • Text - 첫번째 라인에 표시할 텍스트. 큰 폰트를 사용한다.
  • Detail - 두번째 라인에 표시할 텍스트이며 첫번째 라인보다 작은 폰트를 사용한다.
  • TextColor - 첫번째 라인의 텍스트 색상
  • DetailColor - 두번째 라인의 텍스트 색상

    TextCell Samples

    ImageCell

    ImageCell 역시 TextCell과 같이 플랫폼의 네이티브 컨트롤을 사용하여 좋은 성능을 보여준다. TextCell과 다른점은 텍스트의 왼쪽에 이미지를 보여주는 것이다. 그러므로, ImageCell은 TextCell과 동일한 속성에 UmageSource 라는 속성을 추가로 지원한다. 주의할점은, 윈도우폰 8.1에서의 경우 이미지가 자동으로 스케일링이 되지 않아 아래와 같이 보일 수 있다는 점이다.

    IMageCell Samples

    커스텀 셀

    기본셀로 표현하기 어려운경우 커스텀셀을 만들 수 있다. 커스텀셀은 반드시 ViewCell을 상속받아야 한다.
    커스텀셀 샘플

    XAML

    위 샘플 레이아웃은 아래의 XAML코드로 표현될 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?xml version="1.0" encoding="UTF-8"?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="demoListView.ImageCellPage">
    <ContentPage.Content>
    <ListView x:Name="listView">
    <ListView.ItemTemplate>
    <DataTemplate>
    <ViewCell>
    <StackLayout BackgroundColor="#eee"
    Orientation="Vertical">
    <StackLayout Orientation="Horizontal">
    <Image Source="{Binding image}" />
    <Label Text="{Binding title}"
    TextColor="#f35e20" />
    <Label Text="{Binding subtitle}"
    HorizontalOptions="EndAndExpand"
    TextColor="#503026" />
    </StackLayout>
    </StackLayout>
    </ViewCell>
    </DataTemplate>
    </ListView.ItemTemplate>
    </ListView>
    </ContentPage.Content>
    </ContentPage>
  • 커스텀셀 역시 기본셀과 마챦가지로 DataTemplate의 자식이다.
  • 즉, DataTemplate의 자식 요소는 모두 ViewCell의 파생 클래스 이다.

C

XAML과 동일한 과정을 C#코드를 거치게 되면 조금 더 복잡해 진다. 먼저, ViewCell을 상속받는 CustomCell 클래스를 정의하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class CustomCell : ViewCell
{
public CustomCell()
{
//instantiate each of our views
var image = new Image ();
StackLayout cellWrapper = new StackLayout ();
StackLayout horizontalLayout = new StackLayout ();
Label left = new Label ();
Label right = new Label ();
//set bindings
left.SetBinding (Label.TextProperty, "title");
right.SetBinding (Label.TextProperty, "subtitle");
image.SetBinding (Image.SourceProperty, "image");
//Set properties for desired design
cellWrapper.BackgroundColor = Color.FromHex ("#eee");
horizontalLayout.Orientation = StackOrientation.Horizontal;
right.HorizontalOptions = LayoutOptions.EndAndExpand;
left.TextColor = Color.FromHex ("#f35e20");
right.TextColor = Color.FromHex ("503026");
//add views to the view hierarchy
horizontalLayout.Children.Add (image);
horizontalLayout.Children.Add (left);
horizontalLayout.Children.Add (right);
cellWrapper.Children.Add (horizontalLayout);
View = cellWrapper;
}
}

다음은, 페이지의 생성자에서 ListView의 ItemTemplate의 속성을 새로운 DataTemplate으로 설정해야 한다.

1
2
3
4
5
6
7
8
public partial class ImageCellPage : ContentPage
{
public ImageCellPage ()
{
InitializeComponent ();
listView.ItemTemplate = new DataTemplate (typeof(CustomCell));
}
}

DataTemplate의 생성자가 type을 취한것에 주목하라. typeof 오퍼레이터는 CustomCell의 CLR타입을 리턴한다.

컨텍스트 변화 바인딩

CustomCell의 BindableProperty 인스턴스에 바인딩할때, UI컨트롤이 BindableProperty의 값을 보여주기 위해서는 OnBindingContextChanged/)를 오버라이드하여 값을 설정해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class CustomCell : ViewCell
{
Label nameLabel, ageLabel, locationLabel;
public static readonly BindableProperty NameProperty =
BindableProperty.Create ("Name", typeof(string), typeof(CustomCell), "Name");
public static readonly BindableProperty AgeProperty =
BindableProperty.Create ("Age", typeof(int), typeof(CustomCell), 0);
public static readonly BindableProperty LocationProperty =
BindableProperty.Create ("Location", typeof(string), typeof(CustomCell), "Location");
public string Name {
get { return(string)GetValue (NameProperty); }
set { SetValue (NameProperty, value); }
}
public int Age {
get { return(int)GetValue (AgeProperty); }
set { SetValue (AgeProperty, value); }
}
public string Location {
get { return(string)GetValue (LocationProperty); }
set { SetValue (LocationProperty, value); }
}
...
protected override void OnBindingContextChanged ()
{
base.OnBindingContextChanged ();
if (BindingContext != null) {
nameLabel.Text = Name;
ageLabel.Text = Age.ToString ();
locationLabel.Text = Location;
}
}
}

BindingContextChanged 이벤트가 발생하면, OnBindingContextChanged 메소ㄷ가 호출된다. 이 메소드는 BindingContext 의 속성값의 변화에 대한 책임을 진다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class CustomCell : ViewCell
{
Label nameLabel, ageLabel, locationLabel;
public static readonly BindableProperty NameProperty =
BindableProperty.Create ("Name", typeof(string), typeof(CustomCell), "Name");
public static readonly BindableProperty AgeProperty =
BindableProperty.Create ("Age", typeof(int), typeof(CustomCell), 0);
public static readonly BindableProperty LocationProperty =
BindableProperty.Create ("Location", typeof(string), typeof(CustomCell), "Location");
public string Name {
get { return(string)GetValue (NameProperty); }
set { SetValue (NameProperty, value); }
}
public int Age {
get { return(int)GetValue (AgeProperty); }
set { SetValue (AgeProperty, value); }
}
public string Location {
get { return(string)GetValue (LocationProperty); }
set { SetValue (LocationProperty, value); }
}
...
protected override void OnBindingContextChanged ()
{
base.OnBindingContextChanged ();
if (BindingContext != null) {
nameLabel.Text = Name;
ageLabel.Text = Age.ToString ();
locationLabel.Text = Location;
}
}
}

이제 XAML에서, 커스템 셀의 타입을 아래 코드와 같이 데이터에 바인딩할 수 있다.

1
2
3
4
5
6
7
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<local:CustomCell Name="{Binding Name}" Age="{Binding Age}" Location="{Binding Location}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

결과적으로, CustomCell의 Name, Age, Location이라는 Bindable 속성에 콜렉션 객체의 Name, Age, Location 속성이 바인딩 되었다. 이것을 C#코드로 표현하면 아래와 같다.

1
2
3
4
5
6
7
8
9
var customCell = new DataTemplate (typeof(CustomCell));
customCell.SetBinding (CustomCell.NameProperty, "Name");
customCell.SetBinding (CustomCell.AgeProperty, "Age");
customCell.SetBinding (CustomCell.LocationProperty, "Location");
var listView = new ListView {
ItemsSource = people,
ItemTemplate = customCell
};