吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1032|回复: 7
收起左侧

[已解决] C# Winform 如何根据提供的属性名(string)查找Form类控件并赋值

[复制链接]
回帖奖励 7 CB吾爱币 回复本帖可获得 1 CB吾爱币奖励! 每人限 1 次
gksj 发表于 2023-10-1 16:05
本帖最后由 gksj 于 2023-10-20 18:53 编辑

sshot-1.png
using System;
using System.Reflection;
using System.Windows.Forms;

namespace DianZan.sOptions
{
    class ReadOptions
    {
        public ReadOptions(Form rform)
        {
            Forms = rform;        //传递Form本地化
            fieldInfoList = Forms.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);//获取窗体下所有控件集合
        }

        private Form Forms { get; set; }

        private FieldInfo[] fieldInfoList { get; set; }

               private void R2ReadLangData()
        {
            foreach (LangOption co in OptionData.LangList)        //数据拆包
            {
                string rName = co.Name;                                //控件Name属性
                string rText = co.Text;                                //控件Text属性
                foreach (FieldInfo fi in fieldInfoList)
                {
                    try
                    {
                        Type fType = fi.FieldType;           //获取操作数据所在类

                        object control = Convert.ChangeType(rText, fType.GetProperty(rName).PropertyType);//修改对应属性的值 (每次到这里都提示未将对象引用设置的实例)

                        fType.GetProperty(rName).SetValue(fi, control, null);    //赋值

                    }
                    catch (Exception ex)
                    {
                        string errStr = ex.Message;
                    }
                }
            }

        }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DianZan.sOptions
{
    struct LangOption
    {
        public string Name { get; set; }

        public string Text { get; set; }
    }

    class OptionData
    {
        public static List<LangOption> LangList { get; set; }

    }
}


## 保存的数据格式参考

https://www.52pojie.cn/thread-1839902-1-1.html

最早的方案是用Control.Find实现的,但是因为StatusStrip类不是继承自Control,所以这个方法就失效了,希望各位大神帮帮忙


还有几种控件也不是继承自Control,所以最终想到反射这个没有办法的办法
在这之前用了3天时间已经把StatusStrip和所有下属的容器子类都拆明白了,数据已经全部取到,现在读取遇到问题了

主要的目的就是从文本中读取配置,配置里面存着这个控件的Name和Text(当然不同类型控件还有其他值)
然后根据Name名称给这个控件指定的属性赋值.

感谢@pjy612 提供的代码和思路,问题已解决
[C#] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private string R2ReadLangData(FileOptType fileOptType)
      {
          string rStr = OptionFile.aOptFile(fileOptType);    //默认配置参数
 
          foreach (FieldInfo field in fieldInfoList)
          {
              var fType = field.FieldType;                  //获取类型
              var fObj = field.GetValue(Forms);             //获取类型数据
              var fName = fType.GetProperty("Name");
              if (fName == null)
              {
                  continue;//没有控件对应属性
              }
 
              string cName = (string)fName.GetValue(fObj, null);
              LangOption langOpt = OptionData.LangList.Find(f => f.Name == cName);
              if (langOpt.Name == null)
              {
                  continue;//未找配置文件的索引属性
              }
 
              var cText = fType.GetProperty("Text");
              if (cText == null)
              {
                  continue;//没有控件对应属性
              }
              cText.SetValue(fObj, langOpt.Text, null);
          }
          return rStr;
      }


[C#] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
private string R3ReadOptionData(string filePath, FileOptType fileOptType)
       {
           string rStr = null;
           switch (fileOptType)
           {
               case FileOptType.ReadDefault:
                   rStr = OptionFile.aOptFile(FileOptType.ReadDefault);    //默认配置参数
                   break;
               case FileOptType.ReadOption:
                   rStr = OptionFile.aOptFile(filePath, FileOptType.ReadOption);//用户自定义配置参数
                   break;
           }
 
           foreach (FieldInfo field in fieldInfoList)
           {
               var fType = field.FieldType;                  //获取类型
               var fObj = field.GetValue(Forms);             //获取类型数据
               var fName = fType.GetProperty("Name");
               if (fName == null)
               {
                   continue;//没有控件对应属性
               }
 
               string cName = (string)fName.GetValue(fObj, null);
               CtrOption ctrOpt = OptionData.CtrList.Find(f => f.Name == cName);
               if (ctrOpt.Name == null)
               {
                   continue;//未找配置文件的索引属性
               }
 
               if (fObj is TextBox)
               {
                   ((TextBox)fObj).Text = Convert.ToString(ctrOpt.Value);
               }
 
               if (fObj is ComboBox)
               {
                   ((ComboBox)fObj).SelectedIndex = Convert.ToInt32(ctrOpt.Value);
               }
 
               if (fObj is CheckBox)
               {
                   ((CheckBox)fObj).Checked = Convert.ToBoolean(ctrOpt.Value);
               }
 
           }
           return rStr;
       }

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

womaromar 发表于 2023-10-1 16:37

回帖奖励 +1 CB吾爱币

这个打一个断点看看,会不会可以找出来问题
 楼主| gksj 发表于 2023-10-1 19:29
Raohz520 发表于 2023-10-1 22:49
 楼主| gksj 发表于 2023-10-2 00:47

能写个框架吗?没太看懂
pjy612 发表于 2023-10-3 15:49

回帖奖励 +1 CB吾爱币

本帖最后由 pjy612 于 2023-10-3 22:47 编辑
gksj 发表于 2023-10-1 19:29
@pjy612 大神帮帮忙吧,实在是搞不定了


好像是其他问题。
fType.GetProperty(rName)
这个的时候 先判断下 控件是否有 配置内 对应的 属性。有再改值吧。 或者 控件类型 先 GetProperties  存在你要改值的类型,再动。

实际逻辑看着没啥问题 就是 循环 似乎 外层循环控件比较好。配置 根据 控件Name 或 ID 取字典 来快速对应。没有就直接跳掉比较快。

==========以下无视==========================
...那啥 ... 为啥不试试 GetFields ...
看 Form1.Designer.cs 里面 的控件是 都是字段 不是属性啊。。。
而且 看你起名 都是 Field 了... 怎么用的时候变成 去取 Property 了 。。。
另外 感觉 如果是 多语言的话 不用整个控件都替换吧。。。只需要改改 Text 内容就行吧?

免费评分

参与人数 1吾爱币 +2 热心值 +1 收起 理由
gksj + 2 + 1 谢谢@Thanks!

查看全部评分

pjy612 发表于 2023-10-3 23:05
[C#] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
record LangOpt(string Name, string Text);
private void ReloadLangOpt()
        {
            List<LangOpt> opts = new List<LangOpt>()
            {
                new LangOpt("lblA1","123"),
                new LangOpt("lblA2","456"),
            };
            FieldInfo[] allControls = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
            foreach (FieldInfo field in allControls)
            {
                var controlType = field.FieldType;
                var controlObj = field.GetValue(this);
                var p_name = controlType.GetProperty(nameof(LangOpt.Name));
                if (p_name != null)
                {
                    string controlName = (string)p_name.GetValue(controlObj);
                    LangOpt langOpt = opts.Find(f => f.Name == controlName);
                    if (langOpt != null)
                    {
                        var p_text = controlType.GetProperty(nameof(LangOpt.Text));
                        p_text.SetValue(controlObj, langOpt.Text);
                    }
                }
            }
        }
private void Form1_Load(object sender, EventArgs e)
        {
            ReloadLangOpt();
        }


Form 里面 放了两个 label ,名字 分别是 lblA1 和 lblA2 。 调用 ReloadLangOpt 后 会分别将他们的 Text 改成 123 和 456
 楼主| gksj 发表于 2023-10-20 18:49
pjy612 发表于 2023-10-3 23:05
[mw_shl_code=csharp,true]

record LangOpt(string Name, string Text);

感谢提供的思路,问题已解决,谢谢
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-6-17 20:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表