在最近的工作中遇到很多,類似這種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", "孝感"); } }