WPF Template,ItemsPresenter,ItemContainerStyle,ItemsPanel,contentpresenter

10 篇文章 0 订阅
6 篇文章 0 订阅


我现在有个需求,要求做个像360右上角的配置菜单的按钮,

图片

用Botton和popup可以实现,可我不想写太多事件,这时候我想到了comboBox这个控件,点击出现下拉的内容,真是太符合我的需要了,于是,我就决定定制ComboBox。

首先,默认的ComboBox是一个两行两列的布局,(0,0)(第一行,第一列的位置)位置处是一个编辑控件,(0,1)是个按钮,(1,0)(1,1)是个popup,就是点击出现下拉的位置,popup的显示绑定按钮的状态,于是,我们点击按钮的时候,popup就显示出来,popup区域里面有<ItemsPresenter/>显示combobox的items;

1.默认的ComboBox分析完了,接下来就是定制我的ComBoBox了,首先,我只需要一个按钮,一个菜单,于是,把Combobox的Template定制成只有两行的Grid,第一行是一个Button,第二行是个Popup,显示items内容。默认的button这时候不是透明的,还需要进一步定义我的button,把我的Button变成无边框,透明背景的小图标,改写button的template就可以做到了。然后popup的显示要绑定button的press状态,这样,才能点一下按钮,显示Items;template定制如下:

<Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ComboBox}">
                    <Grid x:Name="MainGrid" SnapsToDevicePixels="true">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
                        </Grid.ColumnDefinitions>
                        <Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom" VerticalOffset="10" HorizontalOffset="-60">
                            <Border   CornerRadius="5" Background="White" Padding="10,5,5,5" Width="120" Height="100">
                                <StackPanel>
                                    <ItemsPresenter/>
                                </StackPanel>
                            </Border>
                        </Popup>
                        <ToggleButton BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" >
                            <ToggleButton.Template>
                                <ControlTemplate TargetType="ToggleButton">
                                    <Image Source="Images/Sys/start.png"/>
                                </ControlTemplate>
                            </ToggleButton.Template>
                        </ToggleButton>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
  
2.这时候基本的模型已经出来了,可是,样式看起来不是很好看

这时候,就要修改每个items的显示方式,items的显示方式是ItemContainerStyle来管理的,所以,定制成如下:

 <Setter Property="ItemContainerStyle">
            <Setter.Value>
                <Style TargetType="ComboBoxItem">
                    <Setter Property="Background" Value="White"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ComboBoxItem">
                                <Border Padding="5" Background="{TemplateBinding Background}">
                                    <TextBlock Text="{TemplateBinding Content}"/>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="true">
                            <Setter Property="Background" Value="LightGray"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Setter.Value>
        </Setter>

这时候,控件就变成这样了


我这里只是简单的进行了边距的调整,没有对其他进行调整;


最后上整个style

<x:Array x:Key="items" Type="sys:String" xmlns:sys="clr-namespace:System;assembly=mscorlib">
        <sys:String>系统设置</sys:String>
        <sys:String>查看消息</sys:String>
        <sys:String>消息订阅</sys:String>
    </x:Array>
    
    <Style x:Key="ComboBoxStyle1" TargetType="{x:Type ComboBox}">
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="ItemsSource" Value="{StaticResource items}"/>
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
        <Setter Property="Padding" Value="4,3"/>
        <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
        <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ComboBox}">
                    <Grid x:Name="MainGrid" SnapsToDevicePixels="true">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
                        </Grid.ColumnDefinitions>
                        <Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom" VerticalOffset="10" HorizontalOffset="-60">
                            <Border   CornerRadius="5" Background="White" Padding="10,5,5,5" Width="120" Height="100">
                                <StackPanel>
                                    <ItemsPresenter/>
                                </StackPanel>
                            </Border>
                        </Popup>
                        <ToggleButton BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" >
                            <ToggleButton.Template>
                                <ControlTemplate TargetType="ToggleButton">
                                    <Image Source="Images/Sys/start.png"/>
                                </ControlTemplate>
                            </ToggleButton.Template>
                        </ToggleButton>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ItemContainerStyle">
            <Setter.Value>
                <Style TargetType="ComboBoxItem">
                    <Setter Property="Background" Value="White"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ComboBoxItem">
                                <Border Padding="5" Background="{TemplateBinding Background}">
                                    <TextBlock Text="{TemplateBinding Content}"/>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="true">
                            <Setter Property="Background" Value="LightGray"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="IsEditable" Value="true">
                <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
                <Setter Property="IsTabStop" Value="false"/>
                <Setter Property="Padding" Value="3"/>
            </Trigger>
        </Style.Triggers>
    </Style>



最后总结:


Template:控件模板,是指整个控件的展示和布局,如ComboBox这个控件,就是分为可编辑区域,点击下啦区域,items的popup区域,template就是管理这些位置的布局;

ItemsPresenter:可以简单理解为占位符,在样式中使用,标记着这个区域是展示该控件的Items;如:ComboBox的下拉列表的可选项。但是,只负责显示,而不能管理如何显示,如果我们要combobox的下啦内容横向排列,该怎么做呢,这时候就要用到ItemsPanel了;

ItemsPanel:就是管理Items的排列方式,如,ComboBox默认是竖直排列的,我们要横着排列,只需要定义ItemsPanel为WrapPanel,就可以了;这时候iTEMS的排列方式已经完成,可我还有特殊要求,比如,让ComboBox的每个项都定制,比如,背景啊,图标啊,这时候,ItemsPanel是无法完成的,就要用到ItemContainerStyle了;

ItemContainerStyle:就是每个项的样式,自己重写,就可以定制出每个项 的样式了;



  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于WPF运行时动态切换ItemsControl.ItemsPanel的问题,我可以为您提供以下思路: 1. 创建多个ItemsPanel,例如:StackPanel、WrapPanel、UniformGrid等。 2. 在XAML文件中,使用Resources定义这些ItemsPanel。 3. 创建一个ItemsControl,并在ItemsControl中使用DataTemplate来定义Item的样式。 4. 在ItemsControl中,使用一个默认的ItemsPanel。 5. 在运行时,根据需要动态切换ItemsControl的ItemsPanel。 6. 在切换时,先从ItemsControl的Resources中获取要切换的ItemsPanel,然后将其设置为ItemsControl的ItemsPanel。 以下是一个简单的示例代码: ```xml <!--MainWindow.xaml--> <Window> <Window.Resources> <ItemsPanelTemplate x:Key="StackPanelTemplate"> <StackPanel/> </ItemsPanelTemplate> <ItemsPanelTemplate x:Key="WrapPanelTemplate"> <WrapPanel/> </ItemsPanelTemplate> <ItemsPanelTemplate x:Key="UniformGridTemplate"> <UniformGrid/> </ItemsPanelTemplate> </Window.Resources> <StackPanel> <StackPanel Orientation="Horizontal"> <Button Content="StackPanel" Click="StackPanel_Click"/> <Button Content="WrapPanel" Click="WrapPanel_Click"/> <Button Content="UniformGrid" Click="UniformGrid_Click"/> </StackPanel> <ItemsControl ItemsSource="{Binding Items}"> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}"/> </DataTemplate> </ItemsControl.ItemTemplate> <!--默认的ItemsPanel--> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl> </StackPanel> </Window> ``` ```csharp //MainWindow.xaml.cs public partial class MainWindow : Window { public ObservableCollection<string> Items { get; set; } public MainWindow() { InitializeComponent(); Items = new ObservableCollection<string>() { "Item 1", "Item 2", "Item 3" }; DataContext = this; } private void StackPanel_Click(object sender, RoutedEventArgs e) { ItemsControl.ItemsPanel = (ItemsPanelTemplate)Resources["StackPanelTemplate"]; } private void WrapPanel_Click(object sender, RoutedEventArgs e) { ItemsControl.ItemsPanel = (ItemsPanelTemplate)Resources["WrapPanelTemplate"]; } private void UniformGrid_Click(object sender, RoutedEventArgs e) { ItemsControl.ItemsPanel = (ItemsPanelTemplate)Resources["UniformGridTemplate"]; } } ``` 在这个示例中,我们创建了三个不同的ItemsPanel,分别是StackPanel、WrapPanel和UniformGrid,然后在XAML文件中使用Resources定义它们。在MainWindow中,我们创建了一个ItemsControl,并在ItemsControl中使用DataTemplate来定义Item的样式,同时设置了一个默认的ItemsPanel。 在运行时,我们通过点击按钮来动态切换ItemsControl的ItemsPanel。在每个按钮的Click事件中,我们从MainWindow的Resources中获取要切换的ItemsPanel,然后将其设置为ItemsControl的ItemsPanel。 希望以上思路能够对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值