WPF 一種帶有多個子集的類ComBox 解決方法

乾杯จุ๊發表於2021-02-02

  在最近的工作中遇到很多,類似這種layUI風格的Combox:

 

   因為WPF原本的控制元件,並不具備這種功能,嘗試重寫Combox的模板,發現無從下手。

  於是嘗試從多個控制元件組合來實現這個功能。

  這裡使用了Popup 來存放資料,發現還不錯。

  將popup分為三列,每個列的列寬設定位自動,當點選其中一個選項的時候,檢索所選,根據字典查到資料,再載入其他列。

  即可實現這種效果

  程式碼如下:

  UI:

WPF 一種帶有多個子集的類ComBox 解決方法
<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>
View Code

Model:

WPF 一種帶有多個子集的類ComBox 解決方法
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;
                

            }
        }
    }
View Code

ViewModel:

WPF 一種帶有多個子集的類ComBox 解決方法
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", "孝感");


        }
    }
View Code

 

相關文章