1

1つのキャンバスで複数の「ページ」を持つアプリのページコンテンツのサムネイルビューを表示するリストボックスを作成しようとしています。はい、それはおそらく最初から始めるのに最適な場所ではありませんが、歴史的な理由から私はそれを持っています。PageDataのObservableCollection(背景を含むページに表示されるすべてのもの)を持つシングルトンの「WorkBook」にデータバインディングするListBoxを実装しました。私が本当に望んでいるのは、ListBoxItemが選択されたときに境界線の色を変更し、そのコンテンツがコレクションをホストするクラスで現在選択されているアイテムである間、その境界線の色を維持できるようにすることです。

私の問題は次のとおりです。-1/プログラムの起動時にリストボックスで最初の項目を選択できません。

2 / ListBoxがフォーカスを失うと、SelectedIndexは常に-1になります(したがって、選択は行われません)

3 /リストボックスに追加すると選択されません(SelectedIndex == -1)

4 /トリガーを使用して、selectedItemの境界線を設定できますが、ListBoxがフォーカスを失うとこれは失われます。ListBoxItemは不透明な画像を表示するため、焦点が合っていないときに選択色を維持する「標準」の方法、つまり

<Style x:Key="PsThumb">
                <Style.Resources>
                    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="White"></SolidColorBrush>
                    <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="White"></SolidColorBrush>
                </Style.Resources>
</Style>

ListBoxの私のコードは次のとおりです:-

<ListBox  x:Name="PageSorter" Style="{StaticResource PsThumb}"  Width="148" BorderThickness="4" HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
        VerticalAlignment="Stretch" ItemsSource="{Binding Pages,Source={StaticResource WorkBook}}" SelectedItem="{Binding Path=CurrentPageData, Mode=TwoWay}" 
         AllowDrop="True" ScrollViewer.VerticalScrollBarVisibility="Auto">
                <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                         <Border x:Name="border" BorderBrush="DarkGray" BorderThickness="4" Margin="2,4,2,4" CornerRadius="5">
                             <Border.Effect>
                                 <DropShadowEffect ShadowDepth="6"/>
                             </Border.Effect>
                             <Image Source="{Binding Thumbnail}" Width="130" Height="95" Stretch="Fill"/>
                         </Border>
                    </Grid>
                        <DataTemplate.Triggers>
                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
                                <Setter TargetName="border" Property="BorderBrush" Value="Red"></Setter>
                            </DataTrigger>
                        </DataTemplate.Triggers>
                    </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
4

1 に答える 1

0

DataTrigger求めていることを実現する最も簡単な方法は、のアイテム内のプロパティにをバインドすることですListBox。以下の例では、クラスにSelectedプロパティを追加しました。Contact

public class Contact : INPCBase
{
    public string Name { get; set; }

    private bool _Selected;
    public bool Selected 
    {
        get { return _Selected; }
        set
        {
            _Selected = value;
            NotifyPropertyChanged("Selected");
        }
    }
}

次に、をにバインドListBoxList<Contact>ます。ユーザーがをチェックするとCheckBox、プロパティが変更され、次に:Selectedがトリガーされます。Style

<Window x:Class="WpfApp.ListboxKeepSelectionWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ListboxKeepSelectionWindow" Height="277" Width="343"
    xmlns:me="clr-namespace:WpfApp">

<Window.Resources>
    <me:ContactList x:Key="sample"/>

    <Style TargetType="ListBoxItem" x:Key="SelectedListBoxItemStyle">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=Selected}" Value="True">
                <Setter Property="BorderBrush" Value="Orange"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

<Grid>
    <ListBox Name="lbxContacts"
             ItemsSource="{StaticResource ResourceKey=sample}"
             SelectionMode="Extended"
             ItemContainerStyle="{StaticResource ResourceKey=SelectedListBoxItemStyle}" 
             SelectionChanged="lbxContacts_SelectionChanged">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <CheckBox IsChecked="{Binding Path=Selected}">
                        <TextBlock Text="{Binding Path=Name}"/>
                    </CheckBox>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

ユーザーがチェックボックスを使用せずにアイテムを選択できるようにするために、この小さなイベントをに追加しましたListBoxContactクラスはINotifyPropertyChangedインターフェースを実装しているため、の値がCheckBox更新され、ユーザーは選択が機能したことを確認できます。

    private void lbxContacts_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        foreach (Contact c in e.AddedItems)
        {
            c.Selected = !c.Selected;
        }
    }

選択したアイテムのリストを取得する場合は、に対してLINQクエリを使用するだけで、ItemsSourceアイテムを取得できますSelected == true

于 2013-01-22T01:44:56.393 に答える