吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 827|回复: 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#] 纯文本查看 复制代码
  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#] 纯文本查看 复制代码
 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#] 纯文本查看 复制代码

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, 2024-11-28 12:52

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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