在WPF ListBox中使用不同的项目控件。

问题描述 投票:0回答:1

我有一个这样的代码。

    <ListBox Name="lstBox" 
        ItemsSource="{Binding ViewModelsView}"
        SelectedItem="{Binding SelectedAlertViewOutput, Mode=OneWayToSource}">
        <ListBox.Style>
            <Style TargetType="{x:Type ListBox}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListBox}">
                            <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" 
                                    Background="{TemplateBinding Background}" Padding="1" >
                                <ScrollViewer Padding="{TemplateBinding Padding}" >
                                    <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                </ScrollViewer>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Setter Property="ItemContainerStyle">
                    <Setter.Value>
                        <Style TargetType="{x:Type ListBoxItem}">
                            <Setter Property="IsSelected" 
                                Value="{Binding AlertRecord.IsSelected, Mode=TwoWay}"/>
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                        <Grid HorizontalAlignment="Stretch">
                                            <Grid.RowDefinitions>
                                                <RowDefinition Height="Auto"/>
                                                <RowDefinition Height="Auto"/>
                                            </Grid.RowDefinitions>
                                            <controls:AlertExpander 
                                                Margin="1" 
                                                Value="{Binding AlertRecord.AlertCategory}" 
                                                IsExpanded="{Binding Path=IsSelected, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                                                IsActive="{Binding AlertRecord.IsActive, Mode=OneWay }"
                                                StartTime="{Binding AlertRecord.Timestamp, Mode=OneWay}"
                                                StopTime="{Binding AlertRecord.EndTimestamp, Mode=OneWay}"
                                                AlertId="{Binding AlertRecord.Id, Mode=OneWay}"
                                            <controls:AlertExpander.Content>
                                            <ContentPresenter>
                                            </ContentPresenter>
                                        </controls:AlertExpander.Content>
                                    </controls:AlertExpander>
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
</ListBox.Style>
<ListBox.Resources>
    <DataTemplate DataType="{x:Type local:AlertUnknownViewModel}">
        <local:AlertUnknownView></local:AlertUnknownView>
    </DataTemplate>
</ListBox.Resources>
<ListBox.ItemTemplate>
    <DataTemplate>
        <Grid Margin="4">
            <ContentPresenter Content="{Binding}"></ContentPresenter>
        </Grid>
    </DataTemplate>
</ListBox.ItemTemplate>

ListBox 使用我的控件 AlertExpander 作为 ListBoxItem.

能否创建一个不仅包括类型为 AlertExpander? 我想让另一种类型的元素也使用其上的参数。AlertExpander 取决于。

我有几种类型的控件,它们接受的参数与 AlertExpander但看起来却不一样,我需要在列表中显示所有类型的元素,而不是只显示 AlertExpander.

AlertExpander.xaml:

<Expander 
<Control.Style>
    <Style TargetType="Expander">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Expander">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>

                        <!-- Header -->
                        <ToggleButton Name="HeaderButton">
                            <ToggleButton.Style>
                                <Style TargetType="ToggleButton">
                                    <Setter Property="IsChecked" Value="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, UpdateSourceTrigger=PropertyChanged}"/>
                                    <Setter Property="IsEnabled" Value="{Binding Path=Expandable, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}}"/>
                                    <Setter Property="Template">
                                        <Setter.Value>
                                            <ControlTemplate TargetType="ToggleButton">
                                                <Grid>
                                                    <Border Grid.Row="1" BorderThickness="1" BorderBrush="Black"
                                                            CornerRadius="{Binding BorderCornerRadius, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}">
                                                    </Border>

                                                    <!-- Border shade -->
                                                    <Border Name="BorderShade" Grid.Row="1"  BorderThickness="1" BorderBrush="Transparent" Visibility="Collapsed"
                                                    </Border>
                                                    <Grid>
                                                        <Grid.RowDefinitions>
                                                            <RowDefinition Height="*"/>
                                                            <RowDefinition Height="*"/>
                                                        </Grid.RowDefinitions>
                                                        <Grid.ColumnDefinitions>
                                                            <ColumnDefinition Width="50"/>
                                                            <ColumnDefinition Width="*"/>
                                                        </Grid.ColumnDefinitions>
                                                        <Image Grid.RowSpan="2" Margin="10">
                                                            <Image.OpacityMask>
                                                                <ImageBrush ImageSource="{Binding SelectedItem.IconSource, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}"/>
                                                            </Image.OpacityMask>
                                                            <Image.Source>
                                                                <MultiBinding Mode="OneWay" Converter="{converters:GrayscaleImageSourceConverter}">
                                                                    <Binding Path="SelectedItem" RelativeSource="{RelativeSource AncestorType=controls:AlertExpander}"/>
                                                                    <Binding Path="IsActive" RelativeSource="{RelativeSource AncestorType=controls:AlertExpander}"/>
                                                                </MultiBinding>
                                                            </Image.Source>
                                                        </Image>
                                                        <StackPanel x:Name="topHeader" Grid.Row="0" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Bottom">
                                                            </StackPanel>
                                                        <Label x:Name="bottomHeader" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top" Background="Transparent" Padding="0,2,0,0" FontSize="9pt"
                                                               Content="{Binding AlertHeaderTime, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}">
                                                        </Label>
                                                    </Grid>
                                                </Grid>
                                                <ControlTemplate.Triggers>
                                                    <Trigger Property="IsMouseOver" Value="true">
                                                        <Setter TargetName="BorderShade" Property="Visibility" Value="Visible"/>
                                                    </Trigger>
                                                    <DataTrigger Binding="{Binding IsAlertHeaderTimeShown, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}" Value="false">
                                                        <Setter TargetName="topHeader" Property="VerticalAlignment" Value="Center"/>
                                                        <Setter TargetName="topHeader" Property="Grid.RowSpan" Value="2"/>
                                                        <Setter TargetName="bottomHeader" Property="Visibility" Value="Hidden"/>
                                                    </DataTrigger>
                                                </ControlTemplate.Triggers>
                                            </ControlTemplate>
                                        </Setter.Value>
                                    </Setter>
                                    <Style.Triggers>
                                        <Trigger Property="IsChecked" Value="true">
                                            <Setter Property="Template">
                                                <Setter.Value>
                                                    <ControlTemplate TargetType="ToggleButton">
                                                        <Grid>
                                                            <Border Grid.Row="1" BorderThickness="1" BorderBrush="Black"
                                                                    CornerRadius="{Binding BorderCornerRadius, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay, Converter={converters:AlertExpanderCornerRadiusTopConverter}}">
                                                                </Border>

                                                            <!-- Border shade -->
                                                            <Border Name="BorderShade" Grid.Row="1"  BorderThickness="1" BorderBrush="Transparent" Visibility="Collapsed"
                                                                    Background="{Binding MouseOverShade, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}"
                                                                    CornerRadius="{Binding BorderCornerRadius, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay, Converter={converters:AlertExpanderCornerRadiusTopConverter}}">
                                                            </Border>
                                                            <Grid>
                                                                <Grid.RowDefinitions>
                                                                    <RowDefinition Height="*"/>
                                                                    <RowDefinition Height="*"/>
                                                                </Grid.RowDefinitions>
                                                                <Grid.ColumnDefinitions>
                                                                    <ColumnDefinition Width="50"/>
                                                                    <ColumnDefinition Width="*"/>
                                                                </Grid.ColumnDefinitions>
                                                                <Image Grid.RowSpan="2" Margin="10">
                                                                    <Image.OpacityMask>
                                                                        <ImageBrush ImageSource="{Binding SelectedItem.IconSource, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}"/>
                                                                    </Image.OpacityMask>
                                                                    <Image.Source>
                                                                        <MultiBinding Mode="OneWay" Converter="{converters:GrayscaleImageSourceConverter}">
                                                                            <Binding Path="SelectedItem" RelativeSource="{RelativeSource AncestorType=controls:AlertExpander}"/>
                                                                            <Binding Path="IsActive" RelativeSource="{RelativeSource AncestorType=controls:AlertExpander}"/>
                                                                        </MultiBinding>
                                                                    </Image.Source>
                                                                </Image>
                                                                <StackPanel x:Name="topHeader" Grid.Row="0" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Bottom">
                                                                    <Label Background="Transparent" Padding="0,0,0,2" FontSize="12pt"
                                                                           FontWeight="{Binding IsActive, Mode=OneWay, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Converter={converters:BoolToFontWeightConverter}}"
                                                                           Content="{Binding AlertHeader, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}">
                                                                        </Label>
                                                                    <Label Background="Transparent" Padding="4,0,0,2" FontSize="12pt"
                                                                           FontWeight="{Binding IsActive, Mode=OneWay, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Converter={converters:BoolToFontWeightConverter}}"
                                                                           Visibility="{Binding IsActive, Mode=OneWay, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Converter={converters:InactiveNoteVisibilityConverter}}"
                                                                           Content="{Binding InactiveNote, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}">
                                                                    </Label>
                                                                </StackPanel>
                                                                <Label x:Name="bottomHeader" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top" Background="Transparent" Padding="0,2,0,0" FontSize="9pt"
                                                                       Content="{Binding AlertHeaderTime, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}">
                                                                </Label>
                                                            </Grid>
                                                        </Grid>
                                                        <ControlTemplate.Triggers>
                                                            <Trigger Property="IsMouseOver" Value="true">
                                                                <Setter TargetName="BorderShade" Property="Visibility" Value="Visible"/>
                                                            </Trigger>
                                                            <DataTrigger Binding="{Binding IsAlertHeaderTimeShown, RelativeSource={RelativeSource AncestorType=controls:AlertExpander}, Mode=OneWay}" Value="false">
                                                                <Setter TargetName="topHeader" Property="VerticalAlignment" Value="Center"/>
                                                                <Setter TargetName="topHeader" Property="Grid.RowSpan" Value="2"/>
                                                                <Setter TargetName="bottomHeader" Property="Visibility" Value="Hidden"/>
                                                            </DataTrigger>
                                                        </ControlTemplate.Triggers>
                                                    </ControlTemplate>
                                                </Setter.Value>
                                            </Setter>
                                        </Trigger>
                                    </Style.Triggers>
                                </Style>
                            </ToggleButton.Style>
                        </ToggleButton>

                        <!-- Content -->
                        <ScrollViewer Name="ContentScrollViewer" Grid.Row="1"
                                      HorizontalScrollBarVisibility="Hidden"
                                      VerticalScrollBarVisibility="Hidden"
                                      HorizontalContentAlignment="Stretch"
                                      VerticalContentAlignment="Bottom"
                                      Visibility="Visible">
                            <Border Name="ExpanderContentBorder" BorderThickness="1,0,1,1" BorderBrush="Black">
                                <ContentPresenter ContentSource="Content"/>
                            </Border>
                        </ScrollViewer>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Control.Style>

在这里输入图像描述

c# wpf xaml
1个回答
0
投票

在我开始写代码之前,我想说的是,这是个任务 数据模板而不是控制模板。该 Template 财产采取 ControlTemplate 并用于定义控件的结构。当你从头开始构建一个控件或对一个控件进行重大修改时,通常会用到这个控件。什么是 想要做的只是改变现有控件中数据的显示方式。为此,有 DataTemplate 属性,如 ItemTemplate.

说完这些,我为你整理了一些代码,至少应该为你指明正确的方向。

<ListBox Name="lstBox" ItemsSource="{Binding ViewModelsView}" SelectedItem="{Binding SelectedAlertViewOutput, Mode=OneWayToSource}">
    <ListBox.Resources>
        <DataTemplate DataType="local:AlertRecord" x:Key="AlertExpanderItem">
            <controls:AlertExpander Margin="1" 
                                    Value="{Binding AlertCategory}" 
                                    IsExpanded="{Binding IsSelected, Mode=TwoWay}"
                                    IsActive="{Binding IsActive, Mode=OneWay }"
                                    StartTime="{Binding Timestamp, Mode=OneWay}"
                                    StopTime="{Binding EndTimestamp, Mode=OneWay}"
                                    AlertId="{Binding Id, Mode=OneWay}"/>
        </DataTemplate>

        <DataTemplate DataType="local:AlertRecord" x:Key="OtherControlItem">
            <controls:OtherControl Margin="1" 
                                   Value="{Binding AlertCategory}" 
                                   IsExpanded="{Binding IsSelected, Mode=TwoWay}"
                                   IsActive="{Binding IsActive, Mode=OneWay }"
                                   StartTime="{Binding Timestamp, Mode=OneWay}"
                                   StopTime="{Binding EndTimestamp, Mode=OneWay}"
                                   AlertId="{Binding Id, Mode=OneWay}"/>
        </DataTemplate>
    </ListBox.Resources>

    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
        </Style>
    </ListBox.ItemContainerStyle>

    <ListBox.ItemTemplate>
        <DataTemplate>
            <ContentControl Content="{Binding}">
                <ContentControl.Style>
                    <Style TargetType="ContentControl">
                        <Setter Property="ContentTemplate" Value="{StaticResource OtherControlItem}"/>

                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Value}" Value="0">
                                <Setter Property="ContentTemplate" Value="{StaticResource AlertExpanderItem}"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ContentControl.Style>
            </ContentControl>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

...

public class AlertRecord
{
    ...

    public bool HasPositiveValue { get { return Value >= 0 } }

    ...
}

我首先定义了两个不同的 ItemTemplate里面的里面 ResourcesListBox. 你可以为每个你需要使用的不同控件定义一个。注意我没有写"AlertRecord."从束缚。这是因为每个 DataTemplate 实例将有 AlertRecord 作为其 DataContext.

జజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజ ItemTemplate 属性,我借鉴了这里的这个答案。https:/stackoverflow.coma101917625086631。. 我做了一个 DataTemplate 带着 ContentControl 并使用 Style 改变 ContentTemplate 基于 DataTriggers. 这让你可以根据你的列表项的属性来改变模板。

根据您的评论,样式设置为"OtherControlItem" (非展开器控制)是默认使用的,而非展开器控制是默认使用的。AlertExpanderItemHasPositiveValue 返回true。HasPositiveValue 是你需要添加到 AlertRecord.

© www.soinside.com 2019 - 2024. All rights reserved.