선택한 경우 ListBox 항목에 대한 WPF DataTemplate 변경


91

항목이 선택되었는지 여부에 따라 ListBox의 항목에 대한 DataTemplate을 변경해야합니다 (선택할 때 다른 / 추가 정보 표시).

문제의 ListBox 항목을 클릭 할 때 (탭을 통해서만) DataTemplate (StackPanel)의 최상위 요소에 GotFocus / LostFocus 이벤트가 표시되지 않고 아이디어가 없습니다.

답변:


184

이 작업을 수행하는 가장 쉬운 방법은 "ItemTemplate"속성이 아닌 "ItemContainerStyle"에 대한 템플릿을 제공하는 것입니다. 아래 코드에서 2 개의 데이터 템플릿을 만듭니다. 하나는 "선택되지 않음"이고 다른 하나는 "선택됨"상태입니다. 그런 다음 항목이 포함 된 실제 "ListBoxItem"인 "ItemContainerStyle"에 대한 템플릿을 만듭니다. 기본 "ContentTemplate"을 "Unselected"상태로 설정 한 다음 "IsSelected"속성이 true 일 때 템플릿을 교체하는 트리거를 제공합니다. (참고 : 단순성을 위해 코드 뒤에있는 "ItemsSource"속성을 문자열 목록으로 설정합니다.)

<Window.Resources>

<DataTemplate x:Key="ItemTemplate">
    <TextBlock Text="{Binding}" Foreground="Red" />
</DataTemplate>

<DataTemplate x:Key="SelectedTemplate">
    <TextBlock Text="{Binding}" Foreground="White" />
</DataTemplate>

<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
    <Setter Property="ContentTemplate" Value="{StaticResource ItemTemplate}" />
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="ContentTemplate" Value="{StaticResource SelectedTemplate}" />
        </Trigger>
    </Style.Triggers>
</Style>

</Window.Resources>
<ListBox x:Name="lstItems" ItemContainerStyle="{StaticResource ContainerStyle}" />

1
감사합니다. 게시물에 <ListBox ItemContainerStyle =”{StaticResource ContainerStyle}”ItemsSource =”{Binding MyData}”/>를 포함하여 블로그에서 검색 할 필요가 없도록하십시오.
Shimmy Weitzhandler

2
ListBox의 ContainerStyle을 설정할 때 발생한 한 가지 문제는 테마와 호환되지 않는다는 것입니다. 귀하의 접근 방식을 사용했지만 WPF Futures 세트의 테마를 적용했을 때 ListBoxItems에는 테마 스타일 대신 기본 스타일이 적용되었습니다. 제 경우에는 검은 색 바탕에 검은 색 텍스트와 일반적인 추함이 있습니다. 나는 여전히 DataTemplate 트리거를 사용하는 다른 접근 방식을 찾고 있습니다.
Benny Jobigan 2010

1
또한 새 ItemContainerStyle이 테마와 호환되도록하려면 테마의 항목을 기반으로해야합니다. 이렇게하려면 BasedOn="{StaticResource {x:Type ListBoxItem}}"ListBox와 함께 사용하십시오 . 이것은 TreeView와 같은 다른 컨트롤에도 적용됩니다.
Benny Jobigan 2010

5
이것을 사용하면서 난해한 XAML 오류가 발생하지 않도록 리소스 섹션의 스타일 위에 DataTemplates를 선언해야한다는 것을 알았습니다. 그것에 대해 미리 알려드립니다.
롭 퍼킨스

8

항목이 선택 될 때 스타일을 설정하거나해야 할 일이 전부가 아닐 때 ListBoxItem부모 를 검색하고 <DataTemplate>변경 될 때 스타일 변경을 트리거하는 것입니다 IsSelected. 예를 들어 아래 코드는 TextBlock기본 Foreground색상이 green 입니다. 이제 항목이 선택되면 글꼴이 빨간색으로 바뀌고 마우스가 항목 위에 있으면 노란색으로 바뀝니다 . 이렇게하면 약간 변경하려는 모든 상태에 대해 다른 답변에서 제안한대로 별도의 데이터 템플릿을 지정할 필요가 없습니다.

<DataTemplate x:Key="SimpleDataTemplate">
    <TextBlock Text="{Binding}">
        <TextBlock.Style>
            <Style>
                <Setter Property="TextBlock.Foreground" Value="Green"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={
                        RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem }}}"
                                 Value="True">
                        <Setter Property="TextBlock.Foreground" Value="Red"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={
                        RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem }}}"
                                 Value="True">
                        <Setter Property="TextBlock.Foreground" Value="Yellow"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>
</DataTemplate>

1
질문에서 썼 듯이 선택하면 실제로 더 많은 정보를 표시하고 있습니다 ( "선택하면 다른 정보 / 추가 정보 표시 "). 그래도 일부 요소 (크기 차지 여부 포함)의 가시성을 전환하여 작동하도록 만들 수 있다면 실행 가능한 솔루션이 될 것입니다. 한동안 WPF로 작업하지 않았습니다.
Daniel Beck

6

또한 스택 패널은 초점을 맞출 수 없으므로 초점을 얻지 못할 것입니다 (/ 정말로 / 초점을 맞추려면 Focusable = True 설정). 그러나 이와 같은 시나리오에서 기억해야 할 핵심은 Stackpanel 이이 경우 ItemContainer 인 TreeViewItem의 자식 이라는 것입니다. Micah가 제안했듯이 itemcontainerstyle을 조정하는 것은 좋은 접근 방식입니다.

아마도 DataTemplates와 RelativeSouce 마크 업 확장을 사용하여 listviewitem을 찾는 datatrigger와 같은 것들을 사용하여 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.