首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在使用自定义TemplateBindings和自定义ListBoxItem时保持ListBoxItem

如何在使用自定义TemplateBindings和自定义ListBoxItem时保持ListBoxItem
EN

Stack Overflow用户
提问于 2015-07-28 10:11:36
回答 1查看 189关注 0票数 1

我希望在自定义ListBoxItem中使用自定义ListBox,并希望能够在绑定到ItemSource时在ListBox DataTemplate中绑定自己的属性。

这件事我什么也没发现。我发现的组合总是在Xaml声明的ItemContainerStyle或ItemTemplate样式中,但没有任何与我的情况相近的自定义类。也许我做了什么可怕的错事?

定制的ListBox类:

代码语言:javascript
复制
public class WPM_ListBox : ListBox
{
    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return (item is WPM_ListBoxItem);
    }

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

    public WPM_ListBox()
    {
        this.DefaultStyleKey = typeof(WPM_ListBox);
    }

    static WPM_ListBox()
    {

    }
}

这是WPM_ListBoxItem类的简短版本:

代码语言:javascript
复制
    public class WPM_ListBoxItem : ListBoxItem
{
    public WPM_ListBoxItem()
    {
        this.DefaultStyleKey = typeof(WPM_ListBoxItem);
    }
    static WPM_ListBoxItem()
    {
        BackgroundProperty.OverrideMetadata(typeof(WPM_ListBoxItem), 
            new FrameworkPropertyMetadata((SolidColorBrush)(new BrushConverter().ConvertFrom("#66767A"))));
    }

    public string WPM_HeaderContent
    {
        get { return (string)GetValue(WPM_HeaderContentProperty); }
        set { SetValue(WPM_HeaderContentProperty, value); }
    }
    public static readonly DependencyProperty WPM_HeaderContentProperty =
        DependencyProperty.Register("WPM_HeaderContent", typeof(string), 
        typeof(WPM_ListBoxItem), new PropertyMetadata("WPM_HeaderContent"));
}

下面是Generic.xaml:

代码语言:javascript
复制
<Style x:Key="ItemStyle" TargetType="local:WPM_ListBoxItem" >
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="FontFamily" Value="Arial"/>
    <Setter Property="Foreground" Value="#E9EEEE" x:Name="foreground"/>
    <Setter Property="IsHitTestVisible" Value="True"/>
    <Setter Property="Background" Value="Transparent" x:Name="Background_Property"/>
    <Setter Property="BorderBrush" Value="#67767A"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="FontWeight" Value="Bold"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:WPM_ListBoxItem" >
                <local:WPM_Border IsHitTestVisible="True" Background="Transparent" Margin="1" VerticalAlignment="Top" x:Name="border" Theme="grau" BorderThickness5="1 1 0 0" BorderThickness4="1 1 0 0" BorderThickness3="1 1 0 0" BorderThickness2="1 1 0 0" BorderThickness1="1 1 0 0" >
                    <local:WPM_Border.Data>
                        <Grid x:Name="grid"  IsHitTestVisible="True" Background="Transparent" Margin="0" >
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition MinWidth="45" Width="Auto"/>
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>

                            <Grid.RowDefinitions>
                                <RowDefinition x:Name="row1" />
                                <RowDefinition x:Name="row2" />
                            </Grid.RowDefinitions>

                            <TextBlock VerticalAlignment="Top" FontFamily="Arial" FontWeight="Normal" FontSize="{TemplateBinding WPM_HeaderContenFontSize}" Margin="{TemplateBinding WPM_HeaderContentMargin}" Text="{TemplateBinding WPM_HeaderContent}" Foreground="{TemplateBinding WPM_HeaderContentBrush}" Padding="0 2 0 0" x:Name="headercontent" Grid.ColumnSpan="2" ScrollViewer.CanContentScroll="False"/>
                            <!--<ContentPresenter />-->

                            <StackPanel Margin="3 3 0 0" Grid.Row="1" x:Name="stackpanel1" >
                                <TextBlock HorizontalAlignment="Right" VerticalAlignment="Top" FontWeight="Normal" FontSize="{TemplateBinding WPM_LabelDescriptionFontSize}" Margin="{TemplateBinding WPM_LabelDescriptionMargin}" Text="{TemplateBinding WPM_LabelDescription1}" Foreground="{TemplateBinding WPM_LabelDescriptionBrush1}"/>
                                <TextBlock HorizontalAlignment="Right" VerticalAlignment="Top" FontWeight="Normal" FontSize="{TemplateBinding WPM_LabelDescriptionFontSize}" Margin="{TemplateBinding WPM_LabelDescriptionMargin}" Text="{TemplateBinding WPM_LabelDescription2}" Foreground="{TemplateBinding WPM_LabelDescriptionBrush2}"/>
                            </StackPanel>

                            <StackPanel Margin="3 3 0 0" Grid.Row="1" Grid.Column="1" x:Name="stackpanel2" >
                                <TextBlock VerticalAlignment="Top" FontWeight="Normal" FontSize="{TemplateBinding WPM_LabelContentFontSize}" HorizontalAlignment="Left" Margin="{TemplateBinding WPM_LabelContentMargin}" Text="{TemplateBinding WPM_LabelContent1}" Foreground="{TemplateBinding WPM_LabelContentBrush1}"/>
                                <TextBlock VerticalAlignment="Top" FontWeight="Normal" FontSize="{TemplateBinding WPM_LabelContentFontSize}" HorizontalAlignment="Left" Margin="{TemplateBinding WPM_LabelContentMargin}" Text="{TemplateBinding WPM_LabelContent2}" Foreground="{TemplateBinding WPM_LabelContentBrush2}"/>
                            </StackPanel>

                        </Grid>
                    </local:WPM_Border.Data>
                </local:WPM_Border>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="true">
                        <Setter TargetName="row2" Property="Height" Value="Auto"/>
                        <Setter TargetName="border" Property="Height" Value="Auto"/>
                        <Setter Property="Height" Value="Auto"/>
                        <Setter TargetName="border" Property="BorderThickness1" Value="1 1 0 0"/>
                        <Setter TargetName="border" Property="BorderThickness2" Value="1 1 0 0"/>
                        <Setter TargetName="border" Property="BorderThickness3" Value="1 1 0 0"/>
                        <Setter TargetName="border" Property="BorderThickness4" Value="1 1 0 0"/>
                        <Setter TargetName="border" Property="BorderThickness5" Value="1 1 0 0"/>
                        <Setter TargetName="headercontent" Property="Padding" Value="3 2 0 0"/>
                    </Trigger>
                    <Trigger Property="IsSelected" Value="false">
                        <Setter TargetName="row2" Property="Height" Value="0"/>
                        <Setter TargetName="border" Property="Height" Value="35"/>
                        <Setter Property="Height" Value="35"/>
                        <Setter TargetName="border" Property="BorderThickness1" Value="0"/>
                        <Setter TargetName="border" Property="BorderThickness2" Value="0"/>
                        <Setter TargetName="border" Property="BorderThickness3" Value="0"/>
                        <Setter TargetName="border" Property="BorderThickness4" Value="0"/>
                        <Setter TargetName="border" Property="BorderThickness5" Value="0"/>
                        <Setter TargetName="headercontent" Property="Padding" Value="0 2 0 0"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="BoxStyle" TargetType="local:WPM_ListBox">
    <Setter Property="Padding" Value="1"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="VerticalContentAlignment" Value="Top"/>
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
    <Setter Property="KeyboardNavigation.TabNavigation" Value="Once"/>
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel/>
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:WPM_ListBox">
                <Grid>
                    <ScrollViewer x:Name="PART_ScrollViewer"
                            IsTabStop="False"
                            Margin="0"
                            >
                        <ItemsPresenter/>
                    </ScrollViewer>
                    <ContentPresenter x:Name="PART_DropVisualPlaceholder" Visibility="Collapsed" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemContainerStyle" Value="{StaticResource ItemStyle}"></Setter>
</Style>

<Style TargetType="local:WPM_ListBoxItem" BasedOn="{StaticResource ItemStyle}"/>
<Style TargetType="local:WPM_ListBox" BasedOn="{StaticResource BoxStyle}"/>

在Xaml中,我想这样使用它:

代码语言:javascript
复制
<local:WPM_ListBox ItemsSource="{Binding RoutenListe}" Grid.Row="1" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" BorderThickness="0" Margin="0" Padding="0" Background="#32557B" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto" >
                <local:WPM_ListBox.ItemTemplate  >
                    <DataTemplate >
                        <local:WPM_ListBoxItem WPM_HeaderContent="{Binding Name}" 
                                               WPM_LabelContent1="{Binding Startort}"  WPM_LabelContent2="{Binding Zielort}" 
                                               Background="Transparent" WPM_HeaderContentMargin="6 2 0 0" WPM_HeaderContenFontSize="24" WPM_LabelContentMargin="3 -4 0 3" 
                                               WPM_LabelDescription1="Start:"  WPM_LabelDescription2="Ziel:" WPM_LabelDescriptionMargin="10 -4 0 3" />
                    </DataTemplate>
                </local:WPM_ListBox.ItemTemplate>
            </local:WPM_ListBox>

我知道我可以用ContentPresenter替换声明的控件,然后只需在DataTemplate中使用标签或其他东西。但这不是属地的目的吗?

如果我使用标准ListBox并在ListBoxItem中使用自定义的DataTemplate,则会显示我的数据(绑定数据),但是"IsSelected“触发器将不再工作。如果我使用自定义ListBox与在DataTemplate中声明的自定义属性一起使用,那么只显示我声明的属性(从声明的DependencyProperties中显示StandardValues),而不显示绑定,但IsSelected属性可以工作。

我甚至尝试将所有的背景属性设置为透明的,以确保HitTest不会失败。

我错过了什么吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-28 10:47:46

你用错了ItemTemplateItemTemplate用于为ListBoxItem的内容提供模板,因此不应该包含ListBoxItem。

选项1

从视图中删除ItemTemplate

代码语言:javascript
复制
<local:WPM_ListBox ItemsSource="{Binding RoutenListe}" 
                   Grid.Row="1" 
                   HorizontalContentAlignment="Stretch" 
                   HorizontalAlignment="Stretch" 
                   BorderThickness="0" Margin="0" Padding="0" 
                   Background="#32557B" 
                   ScrollViewer.CanContentScroll="True" 
                   ScrollViewer.VerticalScrollBarVisibility="Auto" />

由于您已经完成了它,所以WPM_ListBox使用WPM_ListBoxItem作为它的默认项容器,并且您已经设置了ItemContainerStyle,它将自动生成它们,并且样式将自动应用于它们。

编辑2:问题是,在这种情况下,您的WPM_ListBox有一系列没有人设置的属性,因此它们保留在默认值中。为了设置这些属性,您可以再次使用ItemContainerStyle,并使用绑定将属性绑定到DataContext中的值:

代码语言:javascript
复制
<local:WPM_ListBox ItemsSource="{Binding RoutenListe}" 
                   Grid.Row="1" 
                   HorizontalContentAlignment="Stretch" 
                   HorizontalAlignment="Stretch" 
                   BorderThickness="0" Margin="0" Padding="0" 
                   Background="#32557B" 
                   ScrollViewer.CanContentScroll="True" 
                   ScrollViewer.VerticalScrollBarVisibility="Auto">
    <local:WPM_ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type local:WPM_ListBoxItem}"
               BasedOn="{StaticResource ItemStyle}">
            <Setter Property="WPM_HeaderContent"
                    Value="{Binding Name}" />
            <Setter Property="WPM_LabelContent1"
                    Value="{Binding Startort}" />

            <!-- Etc. -->

        </Style>
    </local:WPM_ListBox.ItemContainerStyle>
</local:WPM_ListBox>

(编辑:如果您想自定义某个特定项的内容,则需要在您的ContentPresenter模板中使用WPM_ListBoxItem,然后使用ItemTemplate指定如何在该特定列的ContentPresenter中显示数据)

选项2

与其重写ListBox的默认项容器,不如将WPM_ListBoxItem用作常规的ContentControl或类似的东西,并将其添加到ListBoxItemTemplate中,更改绑定到实际ListBoxItemIsSelected属性(现在是ListBox生成的常规属性)的Triggers for DataTriggers

WPM_ListBoxItem.cs:

代码语言:javascript
复制
public class WPM_ListBoxItem : ContentControl
{
    ...
}

您的WPM_ListBoxItem样式触发:

代码语言:javascript
复制
<ControlTemplate.Triggers>
    <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" Value="true">
        <Setter TargetName="row2" Property="Height" Value="Auto"/>
        <Setter TargetName="border" Property="Height" Value="Auto"/>
        <Setter Property="Height" Value="Auto"/>
        <Setter TargetName="border" Property="BorderThickness1" Value="1 1 0 0"/>
        <Setter TargetName="border" Property="BorderThickness2" Value="1 1 0 0"/>
        <Setter TargetName="border" Property="BorderThickness3" Value="1 1 0 0"/>
        <Setter TargetName="border" Property="BorderThickness4" Value="1 1 0 0"/>
        <Setter TargetName="border" Property="BorderThickness5" Value="1 1 0 0"/>
        <Setter TargetName="headercontent" Property="Padding" Value="3 2 0 0"/>
    </Trigger>
    <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" Value="false">
        <Setter TargetName="row2" Property="Height" Value="0"/>
        <Setter TargetName="border" Property="Height" Value="35"/>
        <Setter Property="Height" Value="35"/>
        <Setter TargetName="border" Property="BorderThickness1" Value="0"/>
        <Setter TargetName="border" Property="BorderThickness2" Value="0"/>
        <Setter TargetName="border" Property="BorderThickness3" Value="0"/>
        <Setter TargetName="border" Property="BorderThickness4" Value="0"/>
        <Setter TargetName="border" Property="BorderThickness5" Value="0"/>
        <Setter TargetName="headercontent" Property="Padding" Value="0 2 0 0"/>
    </Trigger>
</ControlTemplate.Triggers>

你的观点是XAML:

代码语言:javascript
复制
<ListBox ItemsSource="{Binding RoutenListe}" Grid.Row="1" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" BorderThickness="0" Margin="0" Padding="0" Background="#32557B" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto">
    <local:WPM_ListBox.ItemTemplate>
        <DataTemplate>
            <local:WPM_ListBoxItem WPM_HeaderContent="{Binding Name}" 
                                   WPM_LabelContent1="{Binding Startort}"  WPM_LabelContent2="{Binding Zielort}" 
                                   Background="Transparent" WPM_HeaderContentMargin="6 2 0 0" WPM_HeaderContenFontSize="24" WPM_LabelContentMargin="3 -4 0 3" 
                                   WPM_LabelDescription1="Start:"  WPM_LabelDescription2="Ziel:" WPM_LabelDescriptionMargin="10 -4 0 3" />
        </DataTemplate>
    </local:WPM_ListBox.ItemTemplate>
</ListBox>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31673317

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档