WPF: сохранение стиля по умолчанию при наследовании от ListBoxItem

Привет, ребята (и девушки, если есть :)

Мне нужна была другая политика выбора списка, чем та, которая предоставляется по умолчанию для списков WPF, т. е. иметь возможность иметь расширенный выбор без какого-либо ключа-модификатора.

С этим проблем нет, вот что я сделал:

class EnhancedCcyPairListBox : ListBox
{

    protected override DependencyObject GetContainerForItemOverride()
    {
        return new CcyPairListBoxItem();
    }

}

internal class CcyPairListBoxItem : ListBoxItem
{
    protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        IsSelected = !IsSelected;

        e.Handled = true;
    }
}

Я не могу сказать, лучший ли это способ, но, похоже, он работает именно так, как я ожидал.

За исключением того, что... сделав это, я потерял стиль ListBoxItem по умолчанию, который у меня был раньше. Как я могу сообщить своим производным классам, чтобы они сохраняли стиль по умолчанию?

Большое спасибо !


person Bruno    schedule 14.03.2011    source источник


Ответы (2)


Добавьте это выше объявления EnhancedCcyPairListBox.

    [StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(CcyPairListBoxItem))]

Редактировать

Добавьте это в статический конструктор CcyPairListBoxItem"

            DefaultStyleKeyProperty.OverrideMetadata(
            typeof(CcyPairListBoxItem), new FrameworkPropertyMetadata(typeof(CcyPairListBoxItem)));

и в Themes/Generic.xaml добавить

<Style TargetType="{x:Type CcyPairListBoxItem}"
       BasedOn="{StaticResource {x:Type ListBoxItem}}"/>
person NVM    schedule 14.03.2011
comment
Спасибо за ваш ответ, но это не работает. И мне это не кажется удивительным, потому что, в конце концов, эта строка кода просто указывает списку использовать стиль CcyPairListBoxItem, и именно в этом и заключается настоящая проблема. - person Bruno; 14.03.2011
comment
Нет, все еще не работает: я не могу получить базовый стиль ListBoxItem. Это кажется безумием, что каждый раз, когда вы наследуете от существующего элемента управления WPF, это должно быть таким беспорядком, чтобы просто получить базовый стиль элемента управления O_o. Я продолжу расследование... - person Bruno; 14.03.2011
comment
@Bruno Последний комментарий указывает на то, что это не решило вашу проблему, но вы отметили это как ответ. Это действительно решило проблему? - person Lynn Crumbling; 16.02.2015

Поскольку контекст WPF нашего приложения весьма специфичен, я хотел убедиться, что проблема не слишком специфична.

Поэтому я взял два вышеупомянутых класса и импортировал их в совершенно новый тестовый проект WPF. Я создал каталог Themes, в котором зарегистрирован словарь ресурсов, в который я поместил Style, как упоминалось ранее NVM.

Структура проекта

Содержимое Generic.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="pack://application:,,,/InheritedListBoxStyling;component/Themes/Styles/TempDic.xaml" />
    <!-- Reference here the Resource dictionnary used for your own component -->
</ResourceDictionary.MergedDictionaries>

</ResourceDictionary>

Содержимое TempDic.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:InheritedListBoxStyling="clr-namespace:InheritedListBoxStyling">

<Style TargetType="{x:Type InheritedListBoxStyling:CcyPairListBoxItem}"        
       BasedOn="{StaticResource {x:Type ListBoxItem}}"/>

</ResourceDictionary>

Содержимое Window1.xaml.cs

namespace InheritedListBoxStyling
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            DataContext = this;
            for (int i = 0; i < 50; i++)
            {
                source.Add("toto " + i);
            }

            l1.ItemsSource = source;
            l2.ItemsSource = source;
        }

        public ObservableCollection<string> source = new ObservableCollection<string>();
    }
}

Содержимое Window1.xaml:

<Window x:Class="InheritedListBoxStyling.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:InheritedListBoxStyling="clr-namespace:InheritedListBoxStyling" 
    Title="Window1" Height="300" Width="300">
    <Grid>

        <ListBox x:Name="l1" SelectionMode="Extended" 
             Margin="0,0,12,12"  Height="100" 
             HorizontalAlignment="Right" 
             VerticalAlignment="Bottom" Width="120" />
        <InheritedListBoxStyling:EnhancedCcyPairListBox 
            x:Name="l2" SelectionMode="Extended" 
            Height="100" Margin="12,12,0,0" 
            VerticalAlignment="Top" 
            HorizontalAlignment="Left" Width="120" />
    </Grid>
</Window>

И вот результат:

Пример приложения

=> стиль по умолчанию не применяется, и, как и в моем «реальном случае», единственный тип стиля, который, кажется, применяется, - это стиль выбранного элемента серого цвета.

Любая идея о том, что происходит или что я делаю неправильно?

person Bruno    schedule 14.03.2011
comment
Я не совсем понимаю, что вы имеете ввиду. С чего вы взяли, что стиль по умолчанию не применяется? Я вижу два списка с одинаковым стилем. (Выбранный элемент становится серым, когда поле списка теряет фокус... это ожидаемое поведение) - person NVM; 14.03.2011
comment
Нет, событие, когда выбран список Google, выбранный элемент отображается серым цветом. Но в любом случае, в этом случае проблема, похоже, вызвана e.Handled =true в переопределении события кнопки previewMouse. Удаление этой строки кода приводит к правильному стилю элемента. Итак, ваш ответ был хорошим, и мне нужно найти другой способ добиться желаемого поведения. Я отмечаю этот вопрос как решенный - person Bruno; 15.03.2011
comment
Аааа, я просто предположил, что вы поставили точку останова, чтобы проверить, что элемент управления достигает обработчика previewmousedown!! Кстати, у меня есть сильно настроенный список с настраиваемой политикой выбора, и я должен сообщить, что есть много дополнительных случаев, которые следует учитывать при переопределении политик выбора. Нет единого исправления для чего-либо, связанного с выбором. - person NVM; 15.03.2011
comment
да, это то, что я обнаруживаю прямо сейчас. В любом случае спасибо за ответы ;) - person Bruno; 15.03.2011
comment
@Bruno Это полезная дополнительная информация, но ее не следует добавлять в качестве ответа, поскольку она просто добавляет дополнительную информацию к исходному вопросу. Можете ли вы отредактировать свой вопрос, добавив все из этого ответа, а затем удалить его? - person Lynn Crumbling; 16.02.2015