021.WPF 以MVVM模式控制combox控件显示/隐藏

本节内容需要读者已掌握MVVM绑定的基本知识,详见020篇文章,这里不再重复基础知识,我们是接上期内容继续优化我的mvvm底层类封装

假设我有一个需求,上图软件中,然后我选择了"标准梯形螺纹"那么,我需要粗选螺纹中径这个combox选项是可见的,如果我选择了"非标螺纹",则需要隐藏掉combox,防止用户误操作

这是一个非常典型的 MVVM 场景。在 WPF 中,您不能直接将一个字符串或布尔值绑定到 Visibility 属性,因为 Visibility 属性需要一个 System.Windows.Visibility 枚举值(VisibleHiddenCollapsed)。

UI界面的combox控件显示/隐藏状态是由三个枚举来控制的(Visible、Hidden 或 Collapsed),

故后台控制类的属性并不能直接用来控制combox

要解决这个问题,您需要使用 值转换器 (Value Converter) ,它实现了 IValueConverter 接口。

下面是实现这个功能的详细步骤和代码示例。

一.MVVM绑定类增加一个string属性用来控制

cs 复制代码
  private string _key= "Visible";

  public string Key
  {
      get { return _key; }
      set
      {
          if (_key != value)
          {
              _key = value;
              OnPropertyChanged(nameof(Key));//订阅自己更新
    
          }
      }
  }

步骤二:创建值转换器类 (KeyToVisibilityConverter)

这个转换器的作用是将您的 Key 属性的值(例如,一个字符串)转换为 WPF 认识的 Visibility 枚举值。

假设:

  • 如果 Key 的值是 "Visiblel",则 ComboBox 显示 (Visible)。
  • 否则,信号若是"Hide" 隐藏 (Collapsed)。

新建Control文件夹,把值转换器类放到这个文件夹内

类继承值转换器接口: IValueConverter

把实现这个接口的方法改下如下:

cs 复制代码
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;

namespace NX_Openg.Control
{
    public class KeyToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // 1. 检查传入的值是否为字符串
            if (value is string keyString)
            {
                // 2. 在这里定义控制逻辑
                // 示例:如果 Key 是 "Hide",则返回 Collapsed
                if (keyString == "Hide")
                {
                    return Visibility.Collapsed;//隐藏并清除界面占位
                }
            }

            // 3. 默认返回 Visible(显示)
            return Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

步骤三:在 XAML 中使用转换器

1.在 XAML 文件的顶部或 App.xaml 中引入命名空间(假设您的转换器在 NX_Openg.Control 中)。

XML 复制代码
xmlns:cjp="clr-namespace:NX_Openg.Control" 

2.将转换器实例化为资源,资源路径在cjp映射的文件夹NX_Openg.Control下,资源key自定义命名

为KeyVisConverter

XML 复制代码
 <Window.Resources>
     <cjp:KeyToVisibilityConverter x:Key="KeyVisConverter"/>
 </Window.Resources>

3.将 ComboBox3 的 Visibility 属性绑定到 Screw类对象ScrewIifo的Key 属性,并使用刚刚创建的转换器KeyVisConverter。ScrewIifo是我的MianViewMode的mvvm绑定的子类对象,见020篇文章

XML 复制代码
 Visibility="{Binding ScrewInfo.Key, Converter={StaticResource KeyVisConverter}}"
        

完整的界面代码如下:

XML 复制代码
<Window x:Class="NX_Openg.HomePage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:NX_Openg"
        xmlns:cjp="clr-namespace:NX_Openg.Control" 
        d:DataContext="{d:DesignInstance Type=local:MainViewModel}"
        mc:Ignorable="d"
        Title="机械设计" Height="900" Width="1450" >
    <Window.Resources>
        <cjp:KeyToVisibilityConverter x:Key="KeyVisConverter"/>
    </Window.Resources>


    <Grid Margin="0,4,0,-4">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="669*"/>
            <ColumnDefinition Width="135*"/>
            <ColumnDefinition Width="646*"/>
        </Grid.ColumnDefinitions>
        <TabControl Grid.ColumnSpan="3">
            <TabItem Header="丝杆传动">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition Height="30"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <Grid Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Background="#FFFFE0">
                        <TextBlock HorizontalAlignment="Left" Margin="10,39,0,0" TextWrapping="Wrap" Text="螺杆材质:" VerticalAlignment="Top"/>
                        <ComboBox Name="combox1" HorizontalAlignment="Left" Margin="91,35,0,0" VerticalAlignment="Top" Width="120" SelectionChanged="combox1_SelectionChanged">
                            <ComboBoxItem Content="工具钢9Mn2V" />
                            <ComboBoxItem Content="工具钢CrWMn"/>
                            <ComboBoxItem Content="氮化钢38CrMoA1A"/>
                            <ComboBoxItem Content="40Cr"/>
                            <ComboBoxItem Content="45钢" IsSelected="True"/>
                        </ComboBox>
                        <TextBlock HorizontalAlignment="Left" Margin="223,39,0,0" TextWrapping="Wrap" Text="螺母材质:" VerticalAlignment="Top"/>
                        <TextBlock HorizontalAlignment="Left" Margin="20,5,0,0" TextWrapping="Wrap" Text="{Binding ScrewInfo.Note1}" VerticalAlignment="Top" Foreground="Red"/>
                        <ComboBox Name="combox2" HorizontalAlignment="Left" Margin="303,35,0,0" VerticalAlignment="Top" Width="120" SelectionChanged="combox2_SelectionChanged">
                            <ComboBoxItem Content="青铜"/>
                            <ComboBoxItem Content="耐磨铸铁"/>
                            <ComboBoxItem Content="钢"/>
                            <ComboBoxItem Content="黄铜" IsSelected="True"/>
                        </ComboBox>
                        <RadioButton x:Name="RedRadio1" Content="标准梯螺纹"  GroupName="GB" HorizontalAlignment="Left" Margin="442,39,0,0" VerticalAlignment="Top" IsChecked="True" Checked="RedRadio1_Checked"/>
                        <RadioButton Content="非标梯螺纹" GroupName="GB" HorizontalAlignment="Left" Margin="538,39,0,0" VerticalAlignment="Top" Checked="RedRadio1_Checked"/>
                        <TextBlock HorizontalAlignment="Left" Margin="10,67,0,0" TextWrapping="Wrap" Text="初选螺纹中径:" VerticalAlignment="Top"/>
                        <ComboBox Name="combox3" HorizontalAlignment="Left" Margin="91,63,0,0" VerticalAlignment="Top" Width="120" 
                                  Visibility="{Binding ScrewInfo.Key, Converter={StaticResource KeyVisConverter}}"
                                  SelectionChanged="combox3_SelectionChanged">
                            <ComboBoxItem Content="8" IsSelected="True"/>
                            <ComboBoxItem Content="10"/>
                            <ComboBoxItem Content="12"/>
                            <ComboBoxItem Content="16"/>
                            <ComboBoxItem Content="20"/>
                            <ComboBoxItem Content="24"/>
                        </ComboBox>
                        <TextBlock HorizontalAlignment="Left" Margin="223,67,0,0" TextWrapping="Wrap" Text="自定义中径:" VerticalAlignment="Top"/>
                        <TextBox Name="text_d2" HorizontalAlignment="Left" Margin="303,67,0,0" TextWrapping="Wrap" Text="8" VerticalAlignment="Top" Width="120"/>


                    </Grid>
                    <Grid Grid.Row="0" Grid.Column="1" ></Grid>
                    <Button Grid.Row="1" Grid.Column="1" Content="生成螺母"/>
                </Grid>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
        </TabControl>

    </Grid>
</Window>

四.在后台代码处理它显示隐藏的时机

当radio选中的项目变化时,修改key的值,经过转换器转为枚举后控制ui界面显示和隐藏

cs 复制代码
        private void RedRadio1_Checked(object sender, RoutedEventArgs e)
        {
            // 检查是否选中
            if (RedRadio1.IsChecked == true)
            {
                home.ScrewInfo.GB = true;//选择了标准螺纹
                home.ScrewInfo.Key = "Visible";//combox3显示
              
            }
            else { 
                home.ScrewInfo.GB = false;
                home.ScrewInfo.Key = "Hide";//combox3隐藏
              
            }
           
        }
相关推荐
小北方城市网13 小时前
Redis 分布式锁高可用实现:从原理到生产级落地
java·前端·javascript·spring boot·redis·分布式·wpf
流水线上的指令侠1 天前
补充说明——针对《C#:从 0 到 1 创建基于 NUnit + FlaUI 的 WPF UI 自动化测试项目》
功能测试·ui·c#·自动化·wpf
流水线上的指令侠1 天前
C# 实战:从 0 到 1 搭建基于 NUnit + FlaUI 的 WPF UI 自动化测试项目
功能测试·ui·c#·自动化·wpf·visual studio
贾修行1 天前
.NET 全栈开发学习路线:从入门到分布式
c#·.net·wpf·asp.net core·web api·winforms·services
晓13131 天前
第四章:Redis实战应用及常见问题(下篇)
java·数据库·缓存·wpf
掘根2 天前
【jsonRpc项目】客户端的Requestor模块,RpcCaller模块
wpf
FuckPatience2 天前
WPF ListBoxItem绑定自己在ListBox中的顺序
wpf
天才奇男子3 天前
LVS原理及部署
linux·运维·云原生·wpf·lvs·linux chrony
予枫的编程笔记3 天前
【Redis实战进阶篇1】Redis 分布式锁:从手写实现到 Redisson 最佳实践
redis·分布式·wpf