본문 바로가기
C#/WPF

[WPF] ListView와 SelectedItem

by HJ0216 2024. 3. 10.

최근에 프로젝트를 진행하면서 ListView Control을 하며 어려웠던 부분을 정리하였습니다.

 

👉 기본 환경

- Language: C#, xaml

- IDE: Visual Basic 2022


ListViewItem을 선택했을 때, 해당 Item의 Content와 함께 Complete가 MessageBox에 표시되게 하고 싶습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<Grid>
    <ListView ItemsSource="{Binding ToDoList}"
              SelectedItem="{Binding SelectedToDoItem}"
              >
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Tag}" Width="70"/>
                    <TextBlock Text="{Binding Content}" Width="60"/>
                    <TextBlock Text="{Binding RegisteredDate, StringFormat=yyyy-MM-dd}" Width="80"/>
                    <Button Content="Is it Complete?"
                            Command="{Binding DataContext.CheckCompleteCommand, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}"
                            />
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

 

그래서 SelectedItem을 선언하고 MessageBox에 연결을 하고 실행시켜보면,

 

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
private ToDoItem _selectedToDoItem = new ToDoItem();
/// <summary>
/// Selected ToDoItem
/// </summary>
public ToDoItem SelectedToDoItem
{
    get { return _selectedToDoItem; }
    set 
    {
        _selectedToDoItem = value;
        OnPropertyChanged("SelectedToDoItem");
    }
}
 
private ICommand _checkCompleteCommand;
public ICommand CheckCompleteCommand => _checkCompleteCommand ?? new RelayCommand(CheckCompleteEvent);
 
/// <summary>
/// Check the Selected TODoItem is complete
/// </summary>
/// <param name="obj"></param>
private void CheckCompleteEvent(object obj)
{
    MessageBox.Show(SelectedToDoItem.Content + " is complete? " + SelectedToDoItem.isComplete);
}

 

 

 

프로그램이 거짓말을 하기 시작합니다🥸.

Content도 없고, Complete도 True인데, 빈 값과 bool 타입의 기본값을 반환합니다🥸.

 

당황해하면서 SelectedItem으로 선언된 SelectedToDoItem 쪽으로 중단점을 설정하고 버튼을 클릭해보면 SelectedToDoItem을 타지 않습니다😮.

 

 

분명 버튼이 ListViewItem안에 버튼이 있어서 클릭을 했는데, 버튼은 클릭되지만 정작 Item은 선택이 안되는 이 상황..!

선물 상자 안에 든 선물을 선물 포장을 풀지 않고 얻어낸 듯한 이 애매함🤔..!

 

Grid를 사용했을 때, 요소들을 윈도우 위에다가 올린다는 느낌이 들었는데 버튼도.. 비슷한 동작 아니까 생각을 했습니다.

 

즉, ListViewItem위에 Button을 올려둔 것이라서 버튼을 클릭하면 버튼 동작은 하지만, Item은 클릭되지 않았기 때문에 SelectedItem 요소가 비어있게 되는 것이지요😎.

 

 

 

실제로 버튼 대신 Item 클릭 후, 버튼을 누르면 SelectedItem이 반영됩니다.

 

방법을 찾아보니 ListView의 ItemContainerStyle을 쓰는 게 간단하다고 나와있어서 적용해보았습니다.

 

 

 

 

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
<Grid>
    <ListView ItemsSource="{Binding ToDoList}"
              SelectedItem="{Binding SelectedToDoItem}"
              >
        <ListView.ItemContainerStyle>
            <Style TargetType="{x:Type ListViewItem}">
                <Style.Triggers>
                    <Trigger Property="IsKeyboardFocusWithin" Value="True">
                        <Setter Property="IsSelected" Value="True"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Tag}" Width="70"/>
                    <TextBlock Text="{Binding Content}" Width="60"/>
                    <TextBlock Text="{Binding RegisteredDate, StringFormat=yyyy-MM-dd}" Width="80"/>
                    <Button Content="Is it Complete?"
                            Command="{Binding DataContext.CheckCompleteCommand, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}"
                            />
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

 

Tirgger를 사용했는데, Property가 Keyboard로 선언되어있어서 동작 원리를 찾아보니,

버튼 클릭 시에 키보드 포커스가 버튼으로 이동하게 되면 해당 Item의 Selected를 true로 변경하면서 SelectedItem에 데이터를 넣는 방식이었습니다.

 

 

 

⭐ UI 요소가 어떤 방식으로 그려지는지 생각해보고, 아래 위치해있는 UI 요소에 접근하는 새로운 방법을 알게 되었습니다.

(고마워요 StackOverFlow🔥!)

 

 

 

📚 참고 자료

 

How to make clicking a Button inside a ListBoxItem select the item?

I have a ListBox defined as follows: <ListBox DisplayMember="Name" ItemsSource="{Binding Persons}" ItemTemplate="{StaticResource PeopleDataTemplate}"

stackoverflow.com

 

'C# > WPF' 카테고리의 다른 글

[WPF] 검색과 정렬  (0) 2024.03.10
[WPF] ComboBox와 SelectedItem  (0) 2024.03.10
[WPF] ListView와 ItemsSource  (0) 2024.03.09
[WPF_Mastereclass] MVVM Binding  (1) 2024.02.11
[SingletoneSean] WPF MVVM Tutorials(Commands / Navigation)  (1) 2024.02.10