• WPF 使用Popup和TreeView实现树状下拉框


    效果如图

    单选

    <Grid Margin="15,5,0,15">
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" x:Name="singleHeader" Width="300" Height="30" PreviewMouseDown="singleHeader_PreviewMouseDown" HorizontalAlignment="Left" />
        <Popup Grid.Row="1" x:Name="singlePopup" AllowsTransparency="True" IsOpen="False">
            <TreeView x:Name="singleTree" ItemsSource="{Binding }" Initialized="singleTree_Initialized" SelectedItemChanged="singleTree_SelectedItemChanged">
                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock VerticalAlignment="Center" FontSize="18" Text="{Binding Name}" Margin="2,0,0,0"></TextBlock>
                        </StackPanel>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>
        </Popup>
    </Grid>
    
    private void singleTree_Initialized(object sender, EventArgs e)
    {
        singleDataContext = new ObservableCollection<AdministrationViewModel>();
        var beijing = new AdministrationViewModel() { Name = "北京市", Id = Guid.NewGuid().ToString() };
        beijing.Children.Add(new AdministrationViewModel() { Name = "朝阳区", Id = Guid.NewGuid().ToString() });
        beijing.Children.Add(new AdministrationViewModel() { Name = "海淀区", Id = Guid.NewGuid().ToString() });
        beijing.Children.Add(new AdministrationViewModel() { Name = "通州区", Id = Guid.NewGuid().ToString() });
        singleDataContext.Add(beijing);
        var guangdong = new AdministrationViewModel() { Name = "广东省", Id = Guid.NewGuid().ToString() };
        guangdong.Children.Add(new AdministrationViewModel() { Name = "汕尾市", Id = Guid.NewGuid().ToString() });
        guangdong.Children.Add(new AdministrationViewModel() { Name = "中山市", Id = Guid.NewGuid().ToString() });
        var guangzhou = new AdministrationViewModel() { Name = "广州市", Id = Guid.NewGuid().ToString() };
        guangzhou.Children.Add(new AdministrationViewModel() { Name = "越秀区", Id = Guid.NewGuid().ToString() });
        guangzhou.Children.Add(new AdministrationViewModel() { Name = "海珠区", Id = Guid.NewGuid().ToString() });
        guangzhou.Children.Add(new AdministrationViewModel() { Name = "番禺区", Id = Guid.NewGuid().ToString() });
        guangdong.Children.Add(guangzhou);
        singleDataContext.Add(guangdong);
    
        var trv = sender as TreeView;
        trv.DataContext = singleDataContext;
    }
    
    private void singleTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        var trv = sender as TreeView;
        var trvItem = trv.SelectedItem as AdministrationViewModel;
        //这里是否被选择的条件为是否为叶子结点,也可以使用AdministrationViewModel中的属性灵活控制
        if (trvItem.Children.Count != 0) return;
        singleHeader.Text = trvItem.Name.ToString();
        singlePopup.IsOpen = false;
    }
    
    private void singleHeader_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        singlePopup.Placement = System.Windows.Controls.Primitives.PlacementMode.RelativePoint;
        singlePopup.VerticalOffset = singleHeader.Height;
        singlePopup.StaysOpen = true;
        singlePopup.Height = singleTree.Height;
        singlePopup.Width = singleHeader.Width;
        singlePopup.IsOpen = true;
    }
    

    多选

    <Grid Margin="15,5,0,15">
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" x:Name="multiHeader" Width="300" Height="30" PreviewMouseDown="multiHeader_PreviewMouseDown" HorizontalAlignment="Left" />
        <Popup Grid.Row="1" x:Name="multiPopup" AllowsTransparency="True" IsOpen="False">
            <StackPanel Orientation="Vertical">
                <TreeView x:Name="multiTree" ItemsSource="{Binding }" Initialized="multiTree_Initialized">
                    <TreeView.ItemTemplate>
                        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                            <StackPanel Orientation="Horizontal">
                                <CheckBox IsChecked="{Binding IsChecked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding IsCanChecked,Mode=OneWay}" Checked="CheckBox_CheckedOrUncheck" Unchecked="CheckBox_CheckedOrUncheck"></CheckBox>
                                <TextBlock VerticalAlignment="Center" FontSize="18" Text="{Binding Name}" Margin="2,0,0,0"></TextBlock>
                            </StackPanel>
                        </HierarchicalDataTemplate>
                    </TreeView.ItemTemplate>
                </TreeView>
                <Button Content="Close(关闭)" Click="CloseMultiPopup_Click"></Button>
            </StackPanel>
        </Popup>
    </Grid>
    
    private void multiHeader_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        multiPopup.Placement = System.Windows.Controls.Primitives.PlacementMode.RelativePoint;
        multiPopup.VerticalOffset = multiHeader.Height;
        multiPopup.StaysOpen = true;
        multiPopup.Height = multiTree.Height;
        multiPopup.Width = multiHeader.Width;
        multiPopup.IsOpen = true;
    }
    
    private void multiTree_Initialized(object sender, EventArgs e)
    {
        multiDataContext = new ObservableCollection<AdministrationViewModel>();
        var beijing = new AdministrationViewModel() { Name = "北京市", Id = Guid.NewGuid().ToString() };
        beijing.Children.Add(new AdministrationViewModel() { Name = "朝阳区", Id = Guid.NewGuid().ToString(),IsCanChecked=true });
        beijing.Children.Add(new AdministrationViewModel() { Name = "海淀区", Id = Guid.NewGuid().ToString(), IsCanChecked = true });
        beijing.Children.Add(new AdministrationViewModel() { Name = "通州区", Id = Guid.NewGuid().ToString() });
        multiDataContext.Add(beijing);
        var guangdong = new AdministrationViewModel() { Name = "广东省", Id = Guid.NewGuid().ToString() };
        guangdong.Children.Add(new AdministrationViewModel() { Name = "汕尾市", Id = Guid.NewGuid().ToString(), IsCanChecked = true });
        guangdong.Children.Add(new AdministrationViewModel() { Name = "中山市", Id = Guid.NewGuid().ToString(), IsCanChecked = true });
        var guangzhou = new AdministrationViewModel() { Name = "广州市", Id = Guid.NewGuid().ToString() };
        guangzhou.Children.Add(new AdministrationViewModel() { Name = "越秀区", Id = Guid.NewGuid().ToString(), IsCanChecked = true });
        guangzhou.Children.Add(new AdministrationViewModel() { Name = "海珠区", Id = Guid.NewGuid().ToString(), IsCanChecked = true });
        guangzhou.Children.Add(new AdministrationViewModel() { Name = "番禺区", Id = Guid.NewGuid().ToString(), IsCanChecked = true });
        guangdong.Children.Add(guangzhou);
        multiDataContext.Add(guangdong);
        var trv = sender as TreeView;
        trv.DataContext = multiDataContext;
    }
    
    private static void GetSelectList(List<AdministrationViewModel> selectList, AdministrationViewModel item)
    {
        if(item.Children!=null)
        {
            foreach (var child in item.Children)
            {
                if (child.IsCanChecked && child.IsChecked)
                    selectList.Add(child);
                GetSelectList(selectList, child);
            }
        }
        
    }
    
    private void CheckBox_CheckedOrUncheck(object sender, RoutedEventArgs e)
    {
        var trv = multiTree;
        var data = trv.DataContext as ObservableCollection<AdministrationViewModel>;
        //获得所有被勾选的选项:这里使用IsChecked和IsCanChecked进行判断->可以根据业务改为其他的逻辑
        var selectList = new List<AdministrationViewModel>();
        foreach (var item in data)
        {
            if (item.IsCanChecked && item.IsChecked)
                selectList.Add(item);
            GetSelectList(selectList, item);
        }
        var selectStr = "";
        foreach (var item in selectList)
        {
            selectStr += item.Name + ",";
        }
        selectStr = selectStr.TrimEnd(',');
        multiHeader.Text = selectStr;
    }
    
    private void CloseMultiPopup_Click(object sender, RoutedEventArgs e)
    {
        multiPopup.IsOpen = false;
    }
    

    示例代码

    PopupWithTreeView

    参考资料

    WPF: TreeView inside a ComboBox

  • 相关阅读:
    Jmeter-日期格式转换为时间戳
    Java中异常的处理
    Java中接口的新特性,为接口添加静态方法和默认方法
    Java接口的应用之代理模式
    Java之接口(interface)的理解
    JAVA中使用super调用属性、方法、构造器
    JAVA方法的重写
    Java之方法
    Java之匿名对象
    关于多态性的使用
  • 原文地址:https://www.cnblogs.com/Lulus/p/14042228.html
Copyright © 2020-2023  润新知