【问题标题】:WPF : Keeping default style when inheriting from ListBoxItemWPF:从 ListBoxItem 继承时保持默认样式
【发布时间】:2011-07-15 00:15:20
【问题描述】:

嘿,伙计们(如果有的话,还有女孩们:)

我需要一种与 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 样式。如何告诉我的派生类保持默认样式?

非常感谢!

【问题讨论】:

    标签: wpf listbox listboxitem multipleselection


    【解决方案1】:

    在 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}}"/>
    

    【讨论】:

    • 感谢您的回答,但这不起作用。而且这对我来说似乎并不奇怪,因为毕竟这行代码只是告诉列表框使用 CcyPairListBoxItem 的样式,而这正是真正的问题所在。
    • 不,仍然不起作用:我无法获得基本的 ListBoxItem 样式。这似乎很疯狂,每次您从现有的 WPF 控件继承时,仅检索基本控件样式 O_o 就应该是一团糟。我会继续调查...
    • @Bruno 最后一条评论表明这没有解决您的问题,但您已将其标记为答案。它真的解决了问题吗?
    【解决方案2】:

    因为我们的应用程序的 WPF 上下文非常特殊,所以我想确定这不是一个非常具体的问题。

    所以我把上面的两个类导入到一个全新的WPF测试项目中。我创建了一个主题目录,该目录注册了一个资源字典,其中我将 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>
    

    结果如下:

    => 不应用默认样式,并且在我的“真实案例”问题中,似乎应用的唯一样式是灰色选定项样式。

    知道发生了什么或我做错了什么吗?

    【讨论】:

    • 我不确定你的意思。是什么让您认为未应用默认样式?我看到两个具有相同样式的列表框。 (当列表框失去焦点时,所选项目变为灰色......这是预期的行为)
    • 否,当goog列表框被选中时,选中的项目显示为灰色。但无论如何,在这种情况下,我的问题似乎是由覆盖 previewMouse 按钮​​事件中的 e.Handled =true 引起的。删除这行代码会产生正确的项目样式。所以你的答案是好的,我必须找到另一种方法来实现所需的行为。我将此问题标记为已解决
    • Aaaah 我只是假设你会设置一个断点来检查控制是否到达 previewmousedown 处理程序!顺便说一句,我有一个带有自定义选择策略的高度自定义列表框,我应该建议在覆盖选择策略时要考虑许多边缘情况。与选择相关的任何事情都没有一行修复。
    • 是的,这就是我现在发现的。无论如何,谢谢你的回答;)
    • @Bruno 这是有用的附加信息,但不应作为答案添加,因为它只是为原始问题添加了更多信息。您可以编辑您的问题,添加此答案中的所有内容,然后将其删除吗?
    猜你喜欢
    • 1970-01-01
    • 2013-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-14
    • 2013-07-17
    • 2010-11-09
    • 2021-10-30
    相关资源
    最近更新 更多