所以我尝试为我正在处理的应用程序创建用户控件。它基本上是ToggleButton
旁边的ComboBox
。我能够像设计师想要的那样嘲笑VS2015中用户控件的ComboBox
部分,但我觉得我的方式并不是最好的方式。< / p>
首先,这是一个链接到它的外观截图: https://www.dropbox.com/s/019f4xqgu8r4i0e/DropDown.png
为此,我最终创建了3种不同的ComboBoxItem
样式。第一个将CheckBox
,TextBlock
与ContentPresenter
和Rectangle
放在一起。第二个只有Separator
,而最后一个只有TextBlock
和ContentPresenter
。这是我的XAML,它在UserControl.Resources
部分声明:
<Style x:Key="cbTestStyle" TargetType="{x:Type ComboBoxItem}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Border Name="Border"
Padding="5"
Margin="2"
BorderThickness="2"
CornerRadius="0"
BorderBrush="Transparent">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="75"/>
<ColumnDefinition Width="15"/>
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0"
IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource TemplatedParent}}"/>
<TextBlock Grid.Column="1"
TextAlignment="Left"
Foreground="Black">
<ContentPresenter/>
</TextBlock>
<Rectangle Grid.Column="2"
Stroke="Black"
Width="15"
Height="15"
Fill="{TemplateBinding Foreground}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="Gray"/>
<Setter TargetName="Border" Property="Background" Value="LightGray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="cbSeparatorStyle" TargetType="ComboBoxItem">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Separator/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="cbResetStyle" TargetType="{x:Type ComboBoxItem}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Border x:Name="Border"
Padding="5"
Margin="2"
BorderThickness="2"
CornerRadius="0"
BorderBrush="Transparent">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1">
<ContentPresenter/>
</TextBlock>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="Gray"/>
<Setter TargetName="Border" Property="Background" Value="LightGray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我想我的第一个问题是,这是让ComboBox
看起来像我提供的屏幕截图的最佳方法吗?
当然,还有一些我尚未解决的问题。首先,cbTestStyle
ComboBoxItem
我希望能够动态填充。数据绑定将是我明显的选择,但使用分隔符和&#34;重置&#34;最后的风格,我不知道如何做到这一点。我目前有ComboBoxItem
s&#34;硬编码&#34;在XAML:
<ComboBox x:Name="cbTestSelect"
Height="34"
Width="18"
IsEnabled="False">
<ComboBoxItem Style="{StaticResource cbTestStyle}" Content="Test 1" Foreground="#7FFF0000" Selected="ComboBoxItem_Selected"/>
<ComboBoxItem Style="{StaticResource cbTestStyle}" Content="Test 2" Foreground="#7F00FF00" Selected="ComboBoxItem_Selected"/>
<ComboBoxItem Style="{StaticResource cbTestStyle}" Content="Test 3" Foreground="#7F0000FF" Selected="ComboBoxItem_Selected"/>
<ComboBoxItem Style="{StaticResource cbSeparatorStyle}"/>
<ComboBoxItem Style="{StaticResource cbResetStyle}" Content="Reset all"/>
</ComboBox>
在这个例子中,我理想地想动态创建前三个项目并使用分隔符和&#34;重置&#34;物品保持静止。我对WPF来说还是比较新的。我觉得尝试在WinForms中创建这个控件(这个用户控件将使用的应用程序)将会复杂得多。此外,我还试图引导我们更多地使用WPF。
非常感谢任何有关在线其他问题或教程的帮助或链接。
答案 0 :(得分:4)
解决方案1:
使用CompositeCollection
以便您可以使用DataBinding调出数据项,并使用常规XAML定义硬编码项:
<Window x:Class="WpfApplication31.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication31"
Title="MainWindow" Height="350" Width="525"
x:Name="view">
<Window.Resources>
<DataTemplate DataType="{x:Type local:DataItem}">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsChecked}"/>
<TextBlock Text="{Binding Text}"/>
<Rectangle Stroke="Black" StrokeThickness="1"
Fill="{Binding Color}" Width="20"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ComboBox VerticalAlignment="Center"
HorizontalAlignment="Center"
Width="100" x:Name="Combo">
<ComboBox.Resources>
<CompositeCollection x:Key="ItemsSource">
<CollectionContainer Collection="{Binding DataContext,Source={x:Reference view}}"/>
<Separator Height="10"/>
<Button Content="Clear All"/>
</CompositeCollection>
</ComboBox.Resources>
<ComboBox.ItemsSource>
<StaticResource ResourceKey="ItemsSource"/>
</ComboBox.ItemsSource>
</ComboBox>
</Grid>
</Window>
代码背后:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var colors = new[] {"Red", "Green", "Blue", "Brown", "Cyan", "Magenta"};
this.DataContext =
Enumerable.Range(0, 5)
.Select(x => new DataItem
{
Text = "Test" + x.ToString(),
Color = colors[x],
IsChecked = x%2 == 0
});
}
}
数据项:
public class DataItem
{
public bool IsChecked { get; set; }
public string Text { get; set; }
public string Color { get; set; }
}
结果:
答案 1 :(得分:3)
解决方案2:
使用Expression Blend,您可ComboBox
控制get the XAML for the default Template,并修改此XAML以容纳额外的视觉效果。
你得到的XAML相当长,我不打算在这里发布。您必须将其放在ResourceDictionary
中,并在您定义此ComboBox
的XAML中引用它。
您需要编辑的相关部分是Popup
:
<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
<Themes:SystemDropShadowChrome x:Name="shadow" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=templateRoot}">
<Border x:Name="dropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
<DockPanel>
<Button Content="Clear All" DockPanel.Dock="Bottom"/>
<Separator Height="2" DockPanel.Dock="Bottom"/>
<ScrollViewer x:Name="DropDownScrollViewer">
<Grid x:Name="grid" RenderOptions.ClearTypeHint="Enabled">
<Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
<Rectangle x:Name="opaqueRect" Fill="{Binding Background, ElementName=dropDownBorder}" Height="{Binding ActualHeight, ElementName=dropDownBorder}" Width="{Binding ActualWidth, ElementName=dropDownBorder}"/>
</Canvas>
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</ScrollViewer>
</DockPanel>
</Border>
</Themes:SystemDropShadowChrome>
</Popup>
请注意,我添加了DockPanel
,Button
和Separator
。
然后您可以将ItemsSource正常绑定到DataItem
集合:
<ComboBox ItemsSource="{Binding}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Width="100"/>
结果:
请注意,这种方法比我之前的解决方案好很多,而且此处发布了其他答案,因为它没有在ComboBoxItem
s中包含额外的视觉效果,因此您无法获得选择突出显示对他们来说,这很奇怪。
答案 2 :(得分:2)
您可以将DataTemplateSelector与XAML中定义的DataTemplates一起使用,将某些项类型变量与您绑定的数据一起使用。
public class StyleSelector : DataTemplateSelector
{
public DataTemplate DefaultTemplate
{ get; set; }
public DataTemplate SeparatorTemplate
{ get; set; }
public DataTemplate ResetTemplate
{ get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var type = item as SomeType;
if (type != null)
{
switch (type.SomeItemTypeField)
{
case TypeENum.Separator: return SeparatorTemplate;
case TypeENum.Reset: return ResetTemplate;
default:
return DefaultTemplate;
}
}
return base.SelectTemplate(item, container);
}
}
答案 3 :(得分:1)
我认为最好的办法是了解DataTemplate和DataTemplateSelector。
这是一篇博文,向您展示使用DataTemplate的简单示例。
基本上,您可以将ComboBox绑定到对象集合,并使用DataTemplateSelector根据对象类型选择要使用的模板。