Стиль Listviews Selector.SelectedItem - PullRequest
       0

Стиль Listviews Selector.SelectedItem

0 голосов
/ 28 января 2011

У меня ListView с SelectionMode = расширенный и стиль для ListViewItem таким образом:

MainWindow.xaml:

<Window x:Class="ListViewSelection.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="{x:Type ListViewItem}">
            <Style.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Aqua"/>
            </Style.Resources>
            <!--<Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="Aqua" />
                </Trigger>
            </Style.Triggers>-->
        </Style>
    </Window.Resources>
    <StackPanel>
        <ListView Name="MyListView" ItemsSource="{Binding MyList}" SelectionChanged="SelectionChanged" SelectionMode="Extended" />
        <Label Name="MyLabel" />
    </StackPanel>
</Window>

MainWindow.xaml.cs:

using System.Windows;
using System.Windows.Controls;
using System.Collections.ObjectModel;

namespace ListViewSelection
{
    public partial class MainWindow : Window
    {

        public ObservableCollection<string> MyList { get; set; }

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
            MyList = new ObservableCollection<string>();
            MyList.Add("Jane");
            MyList.Add("Paul");
            MyList.Add("Sally");
            MyList.Add("Ian");
        }

        private void SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            MyLabel.Content = (sender as ListBox).SelectedItem;
        }
    }
}

Это устанавливает цвет отлично для всех выбранных элементов.Но мне нужно также стилизовать Selector.SelectedItem, который является «активным» или первым элементом в выделении.Это тот, который отображается на этикетке.

Любая помощь?Спасибо!

1 Ответ

0 голосов
/ 28 января 2011

Вы можете предоставить свойство IsFirstInSelection в своем классе ViewData (я полагаю, у вас оно есть).

Тогда вы можете разместить DataTrigger для мониторинга изменений, например:

        <Style.Triggers>
            <DataTrigger Binding="{Binding IsFirstInSelection}">
                <Setter Property="Background"
                        Value="Blue"/>
            </DataTrigger>
        </Style.Triggers>

Также в вашем случае я бы рекомендовал избегать изменения HighlightBrushKey, но достигать своей цели путем изменения свойства Background.Вы также можете открыть свойство IsSelected в классе ViewData, чтобы оно выглядело так:

public class ViewData: ObservableObject
{
    private bool _isSelected;
    public bool IsSelected
    {
        get
        {
            return this._isSelected;
        }
        set
        {
            if (this._isSelected != value)
            {
                this._isSelected = value;
                this.OnPropertyChanged("IsSelected");
            }
        }
    }

    private bool _isFirstInSelection;
    public bool IsFirstInSelection
    {
        get
        {
            return this._isFirstInSelection;
        }
        set
        {
            if (this._isFirstInSelection != value)
            {
                this._isFirstInSelection = value;
                this.OnPropertyChanged("IsFirstInSelection");
            }
        }
    }
}

И ваш стиль устанавливает фон на основе обоих свойств:

        <Style x:Key="TreeItemStyle"
               TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsSelected"
                    Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
            <Setter Property="IsFirstInSelection"
                    Value="{Binding Path=IsFirstInSelection}"/>
            <Setter Property="Background"
                    Value="Green"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsSelected}"
                             Value="True">
                    <Setter Property="Background" 
                            Value="Red"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding IsFirstInSelection}">
                    <Setter Property="Background"
                        Value="Blue"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>

Конечно, в модели или в представленииЗа кодом вы должны следить за уведомлениями об изменении свойства IsSelected и устанавливать / сбрасывать IsFirstInSelection в соответствии с выбранными элементами.

Надеюсь, вы понимаете мою идею.

------- РЕДАКТИРОВАНИЕ --------

Сначала я продолжаю настаивать на том, чтобы вы разработали правильный класс ViewData:

public class ViewData : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        var ev = this.PropertyChanged;
        if (ev != null)
        {
            ev(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public ViewData(string name)
    {
        this._personName = name;
    }

    private string _personName;
    public string PersonName
    {
        get
        {
            return this._personName;
        }
        set
        {
            if (this._personName != value)
            {
                this._personName = value;
                this.OnPropertyChanged("PersonName");
            }
        }
    }

    private bool _isFirstSelected;
    public bool IsFirstSelected
    {
        get
        {
            return this._isFirstSelected;
        }
        set
        {
            if (this._isFirstSelected != value)
            {
                this._isFirstSelected = value;
                this.OnPropertyChanged("IsFirstSelected");
            }
        }
    }
}

Во время обработки события SelectionChanged вы должны изменить свойство IsFirstSelected следующим образом:

public ObservableCollection<ViewData> MyList { get; set; }
private void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var lb = sender as ListBox;
    if (lb != null)
    {
        MyLabel.Content = lb.SelectedItem;
        foreach (var item in this.MyList)
        {
            if (item == lb.SelectedItem)
            {
                item.IsFirstSelected = true;
            }
            else
            {
                item.IsFirstSelected = false;
            }
        }
    }
}

Но шаблон ListViewItem по умолчанию не реагирует на установщики фона, поэтому вы должны переопределить его шаблон в стиле:

<Style TargetType="{x:Type ListViewItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListViewItem">
                <Grid Background="{TemplateBinding Background}">
                    <ContentPresenter Content="{Binding PersonName}"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected"
                                Value="True">
                        <Setter Property="Background"
                                Value="Yellow"/>
                    </Trigger>

                    <DataTrigger Binding="{Binding IsFirstSelected}" 
                                    Value="True">
                        <Setter Property="Background" 
                                Value="Aqua" />
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style> 

Если это решение не подходит, пожалуйста, сообщите мне.У меня есть некоторые идеи, но у меня нет достаточно времени, чтобы проверить их в коде прямо сейчас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...