zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    1093 Count PAT's(25 分)
    1089 Insert or Merge(25 分)
    1088 Rational Arithmetic(20 分)
    1081 Rational Sum(20 分)
    1069 The Black Hole of Numbers(20 分)
    1059 Prime Factors(25 分)
    1050 String Subtraction (20)
    根据生日计算员工年龄
    动态获取当前日期和时间
    对计数结果进行4舍5入
  • 原文地址:https://www.cnblogs.com/Lulus/p/14042228.html
Copyright © 2011-2022 走看看