
正文
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", "孝感"); }
}







