WPF 一种带有多个子集的类ComBox 解决方法
在最近的工作中遇到很多,类似这种layUI风格的Combox:

因为WPF原本的控件,并不具备这种功能,尝试重写Combox的模板,发现无从下手。
于是尝试从多个控件组合来实现这个功能。
这里使用了Popup 来存放数据,发现还不错。
将popup分为三列,每个列的列宽设置位自动,当点击其中一个选项的时候,检索所选,根据字典查到数据,再加载其他列。
即可实现这种效果
代码如下:
UI:

<Button x:Name="btn1"
Height="54"
Margin="0,10,0,0"
Click="Button_Click">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Border
Background="Transparent"
CornerRadius="15"
BorderBrush="#6B778D"
BorderThickness="1">
<Grid>
<TextBlock
Text="▼"
Margin="0,0,5,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Foreground="White"
FontSize="20" />
<TextBlock
Text="{Binding Shell6PageModel.DetailedAddress}"
Margin="10,0,0,0"
VerticalAlignment="Center"
Foreground="White"
FontSize="32" />
</Grid>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
<Popup x:Name="pop1"
Width="{Binding ElementName=btn1, Path=ActualWidth}"
Height="260"
AllowsTransparency="True"
IsOpen="False"
Placement="Bottom"
PlacementTarget="{Binding ElementName=btn1}"
PopupAnimation="Slide"
StaysOpen="False">
<Grid>
<Border
Background="Gray"
Opacity="0.9"
BorderBrush="Gray"
BorderThickness="1"
CornerRadius="8" /> <Border>
<Grid HorizontalAlignment="Center">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> <Grid Grid.Column="0">
<ListBox
ItemsSource="{Binding Countries}"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
BorderThickness="0"> <ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<Border x:Name="bord1" />
<ContentPresenter />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="bord1" Property="Background" Value="Transparent" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle> <ListBox.ItemTemplate>
<DataTemplate>
<RadioButton
Content="{Binding DetailedCountry}"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Shell6Page}}, Path=DataContext.countryCommand}"
CommandParameter="{Binding}"
Width="100"
Height="35"
Margin="0,5,0,5"
VerticalAlignment="Center"
Foreground="White"
FontSize="36"
GroupName="0" />
</DataTemplate>
</ListBox.ItemTemplate> </ListBox> </Grid> <Grid Grid.Column="1">
<ListBox
ItemsSource="{Binding Shengs}"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
BorderThickness="0"> <ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<Border x:Name="bord1" />
<ContentPresenter VerticalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="bord1" Property="Background" Value="Transparent" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle> <ListBox.ItemTemplate>
<DataTemplate>
<RadioButton
Content="{Binding DetailedSheng}"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Shell6Page}}, Path=DataContext.shengCommand}"
CommandParameter="{Binding}"
Width="100"
Height="35"
Margin="0,5,0,5"
VerticalAlignment="Center"
Foreground="White"
FontSize="36"
GroupName="1" />
</DataTemplate>
</ListBox.ItemTemplate> </ListBox> </Grid> <Grid Grid.Column="2">
<ListBox
ItemsSource="{Binding Cities}"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
BorderThickness="0">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}"> <Grid>
<Border x:Name="bord1" />
<ContentPresenter />
</Grid> <ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="bord1" Property="Background" Value="Transparent" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle> <ListBox.ItemTemplate>
<DataTemplate>
<RadioButton
Content="{Binding DetailedCity}"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Shell6Page}}, Path=DataContext.cityCommand}"
CommandParameter="{Binding}"
Width="100"
Height="35"
Margin="0,5,0,5"
VerticalAlignment="Center"
Foreground="White"
FontSize="36"
GroupName="2" />
</DataTemplate>
</ListBox.ItemTemplate> </ListBox> </Grid> <Grid Grid.Column="3">
<ListBox
ItemsSource="{Binding Areas}"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
BorderThickness="0">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}"> <Grid>
<Border x:Name="bord1" />
<ContentPresenter />
</Grid> <ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="bord1" Property="Background" Value="Transparent" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle> <ListBox.ItemTemplate>
<DataTemplate>
<RadioButton
Content="{Binding DetailedArea}"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Shell6Page}}, Path=DataContext.areaCommand}"
CommandParameter="{Binding}"
Width="100"
Height="35"
Margin="0,5,0,5"
Foreground="White"
FontSize="36"
Click="RadioButton_Click"
GroupName="3" />
</DataTemplate>
</ListBox.ItemTemplate> </ListBox> </Grid> </Grid> </Grid> </Border> </Grid>
</Popup>
Model:

public class Shell6PageModel:ViewModelBase
{
private string detailedAddress;
/// <summary>
/// 详细地址
/// </summary>
public string DetailedAddress
{
get { return detailedAddress; }
set
{
detailedAddress = value; }
} private string area;
/// <summary>
/// 所在地区
/// </summary>
public string Area
{
get { return area; }
set { area = value; }
}
}
ViewModel:

public class Shell6PageViewModel : ViewModelBase
{
Dictionary<string, string> AddressCity = new Dictionary<string, string>();
Dictionary<string, string> AddressArea = new Dictionary<string, string>();
Dictionary<string, string> AddressSheng = new Dictionary<string, string>();
Dictionary<string, string> AddressCountry = new Dictionary<string, string>();
string[] ad; public Shell6PageViewModel()
{
countryCommand = new RelayCommand<Country>(t => GetCountry(t));
shengCommand = new RelayCommand<Sheng>(t => GetSheng(t));
cityCommand = new RelayCommand<City>(t => GetCity(t));
areaCommand = new RelayCommand<Area>(t => GetArea(t)); Shell6PageModel = new Shell6PageModel()
{
Area = EAppEnvironment.informationInfo.Area, DetailedAddress = EAppEnvironment.informationInfo.DetailedAddress };
InitDictionary();
} private void GetArea(Area t)
{
ad[3] = t.DetailedArea;
Shell6PageModel.DetailedAddress = "";
foreach (var item in ad)
{
Shell6PageModel.DetailedAddress += item;
} } private void GetCity(City t)
{
Areas.Clear(); ad[2] = t.DetailedCity;
Shell6PageModel.DetailedAddress = "";
foreach (var item in ad)
{
Shell6PageModel.DetailedAddress += item;
} foreach (var item in AddressArea)
{
if (t.DetailedCity == item.Value)
{
Areas.Add(new Area { DetailedArea = item.Key }); }
}
} private void GetSheng(Sheng t)
{
Cities.Clear();
Areas.Clear();
ad[1] = t.DetailedSheng;
Shell6PageModel.DetailedAddress = "";
foreach (var item in ad)
{
Shell6PageModel.DetailedAddress += item;
}
foreach (var item in AddressCity)
{
if (t.DetailedSheng == item.Value)
{
Cities.Add(new City() { DetailedCity = item.Key }); }
} } private void GetCountry(Country t)
{
Shengs.Clear();
Cities.Clear();
Areas.Clear();
ad = null;
ad = new string[4];
ad[0] = t.DetailedCountry;
Shell6PageModel.DetailedAddress = "";
foreach (var item in ad)
{
Shell6PageModel.DetailedAddress += item;
}
foreach (var item in AddressSheng)
{
if (t.DetailedCountry == item.Value)
{
Shengs.Add(new Sheng() { DetailedSheng = item.Key });
}
}
} private Shell6PageModel shell6PageModel; public Shell6PageModel Shell6PageModel
{
get { return shell6PageModel; }
set { shell6PageModel = value; RaisePropertyChanged(); }
} public RelayCommand<Sheng> shengCommand { get; set; } public RelayCommand<Country> countryCommand { get; set; } public RelayCommand<City> cityCommand { get; set; }
public RelayCommand<Area> areaCommand { get; set; } private ObservableCollection<Country> countries; public ObservableCollection<Country> Countries
{
get { return countries; }
set { countries = value; RaisePropertyChanged(); }
} private ObservableCollection<Sheng> shengs; public ObservableCollection<Sheng> Shengs
{
get { return shengs; }
set { shengs = value; RaisePropertyChanged(); }
} private ObservableCollection<City> cities; public ObservableCollection<City> Cities
{
get { return cities; }
set { cities = value; RaisePropertyChanged(); }
} private ObservableCollection<Area> areas; public ObservableCollection<Area> Areas
{
get { return areas; }
set { areas = value; RaisePropertyChanged(); }
} public void InitDictionary()
{
Countries = new ObservableCollection<Country>();
Shengs = new ObservableCollection<Sheng>();
Cities = new ObservableCollection<City>();
Areas = new ObservableCollection<Area>(); Countries.Add(new Country() { DetailedCountry = "中国" });
Countries.Add(new Country() { DetailedCountry = "国外" }); AddressSheng.Add("湖北1", "中国");
AddressSheng.Add("湖北2", "中国");
AddressSheng.Add("湖北3", "中国");
AddressSheng.Add("湖北4", "中国");
AddressSheng.Add("湖北5", "中国");
AddressSheng.Add("湖北6", "中国");
AddressSheng.Add("湖北7", "中国");
AddressSheng.Add("湖北8", "中国");
AddressSheng.Add("纽约1", "国外");
AddressSheng.Add("纽约2", "国外");
AddressSheng.Add("纽约3", "国外");
AddressSheng.Add("纽约4", "国外");
AddressSheng.Add("纽约5", "国外");
AddressSheng.Add("纽约6", "国外");
AddressSheng.Add("纽约7", "国外");
AddressSheng.Add("纽约8", "国外"); AddressCity.Add("孝感", "湖北1");
AddressCity.Add("武汉", "湖北1");
AddressCity.Add("襄阳", "湖北1");
AddressCity.Add("十堰", "湖北1");
AddressCity.Add("仙桃", "湖北1");
AddressCity.Add("鄂州", "湖北2");
AddressCity.Add("黄冈", "湖北2");
AddressCity.Add("神农架", "湖北2");
AddressCity.Add("黄石", "湖北2");
AddressCity.Add("恩施", "湖北2");
AddressCity.Add("湖南1", "湖北3");
AddressCity.Add("湖南2", "湖北3");
AddressCity.Add("湖南3", "湖北3");
AddressCity.Add("湖南4", "湖北3");
AddressCity.Add("湖南5", "湖北3");
AddressCity.Add("湖南6", "湖北3");
AddressCity.Add("湖南7", "湖北3"); AddressArea.Add("孝感1", "孝感");
AddressArea.Add("孝感2", "孝感");
AddressArea.Add("孝感3", "孝感");
AddressArea.Add("孝感4", "孝感");
AddressArea.Add("孝感5", "孝感");
AddressArea.Add("孝感6", "孝感");
AddressArea.Add("孝感7", "孝感");
AddressArea.Add("孝感8", "孝感"); }
}
WPF 一种带有多个子集的类ComBox 解决方法的更多相关文章
- 16种C语言编译警告(Warning)类型的解决方法
当编译程序发现程序中某个地方有疑问,可能有问题时就会给出一个警告信息.警告信息可能意味着程序中隐含的大错误,也可能确实没有问题.对于警告的正确处理方式应该是:尽可能地消除之.对于编译程序给出的每个警告 ...
- WebService中使用自定义类的解决方法(5种)
转自:http://www.cnblogs.com/lxinxuan/archive/2007/05/24/758317.html Demo下载:http://files.cnblogs.com/lx ...
- CodedUI Test 测试WPF程序,无法获取控件属性值的解决方法
注意注意!ItemStatus 在VS2010的CUIT里面是没有的!需要2013以上的版本才可使用. 公司新程序使用WPF制作,但使用CodedUI Test进行自动化测试的时候,很多控件抓取不到其 ...
- WPF 四种尺寸单位
原文:WPF 四种尺寸单位 像素 px 默认单位可以省略 厘米cm 英寸 in 点 pt 1in = 96px 1cm=96/2.42px 1pt=96/72px
- WPF 平板上按钮点击不触发,鼠标点击触发的两种解决方法
今天运行在windows平板上的程序,有个功能是弹出子窗体,点弹出窗体的关闭按钮,要点好几次才能触发.网上找了找,也有人与我类似的情形. 解决方法如下: public static void Disa ...
- WPF WebBrowser Memory Leak 问题及临时解决方法
首先介绍一下内存泄漏(Memory Leak)的概念,内存泄露是指程序中已动态分配的堆内存由于某种原因未释放或者无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果. 最近在使用W ...
- Ubuntu几种常见乱码解决方法
一.网页中的flash乱码: ubuntu默认浏览器是Firefox,但是Ubuntu默认不安装像flash这种带版权的软件,所以当你浏览像youku或网页播放器时,这种带有 flash ...
- Spring Boot Maven Plugin打包异常及三种解决方法:Unable to find main class
[背景]spring-boot项目,打包成可执行jar,项目内有两个带有main方法的类并且都使用了@SpringBootApplication注解(或者另一种情形:你有两个main方法并且所在类都没 ...
- PowerDesigner生成Oracle表名带有引号的解决方法
PowerDesigner生成表名带有引号,如下: /*==============================================================*/ /* Tabl ...
随机推荐
- Kafka基本原理概述
Kafka的基本介绍 Kafka是最初由Linkedin公司开发,是一个分布式.分区的.多副本的.多订阅者,基于zookeeper协调的分布式日志系统(也可以当做MQ系统),常见可以用于web/ngi ...
- i5 11300H 怎么样 相当于什么水平
i5-11300H 为 4 核 8 线程,主频 3.1GHz,睿频 4.4GHz,三级缓存 8MBi5-11300H 怎么样看完你就知道了 https://list.jd.com/list.html?
- JVM--理解介绍
JVM?JDK?JRE?关系? JDK(Java Development Kit),它是实际上存在的,它包含JRE+编译.运行等开发工具. JRE(Java Runtime Environment), ...
- Linux设置系统时区
https://www.xlsys.cn/1741.html 如果你的 Linux 系统时区配置不正确,必需要手动调整到正确的当地时区.NTP 对时间的同步处理只计算当地时间与 UTC 时间的偏移量, ...
- java的重载与重写
原文链接http://zhhll.icu/2020/11/11/java%E5%9F%BA%E7%A1%80/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/%E9%87%8 ...
- 【JDBC核心】实现 CRUD 操作
实现 CRUD 操作 操作和访问数据库 数据库连接被用于向数据库服务器发送命令和 SQL 语句,并接受数据库服务器返回的结果.其实一个数据库连接就是一个 Socket 连接. java.sql 包中有 ...
- 阿里云OSS整合
一.对象存储OSS 为了解决海量数据存储与弹性扩容(主要是静态文件的存储例如图片,语音,视频等),项目中我们通常采用云存储的解决方案- 阿里云OSS. 1.开通"对象存储OSS"服 ...
- Neo4j 图数据库查询
Cypher 介绍 Cypher 介绍:作为Neo4j的查询语言,"Cypher"是一个描述性的图形查询语言,允许不必编写图形结构的遍历代码对图形存储有表现力和效率的查询.Cyph ...
- yum -y install gnuplot
[root@test~]# yum -y install gnuplotLoaded plugins: fastestmirrorLoading mirror speeds from cached h ...
- 目前用下来最溜的MacOS微信多开工具!
一个生活微信,一个工作微信是很多上班族的基本配置. 但由于微信客户端在PC端上只能打开一个,这使得在上班时候就非常不便,一个号在PC端上登录,一个在手机上使用,但是上班时候又不能一直看手机,不然老板还 ...