最近研究了一段时间MMVM的数据绑定,目前得出的结论单向绑定就已经够使用了,目前有2种方法实现数据绑定。
方法1 使用一个类代替基础数据
如下代码所示,我使用int32来代替int 数据,这样就可以监听数据绑定了。由于C#并没有提供”=”符号的运算符重载,所以需要.value=xx 来触发数据变化事件,而其它计算,比较等都可使用运算符重载或隐式转换的方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
int32 i32 = new int32(100); //与各类型进行隐式转换 int ii = i32 + 100*2000; float ff = i32; double dd = i32; //数据判断 if (i32 == 10) { } if (i32 <= 10) { } //监听数据变化 i32.valueChange += (change) => { Debug.Log(change); }; //最终设置数值 i32.value = 200; Debug.Log(i32); |
int32.cs核心代码
1 2 3 4 5 6 7 8 9 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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
using System; public struct int32 : IComparable, IFormattable, IComparable<int32>, IEquatable<int32> { private int m_Value; public int value { get { return m_Value; } set { if (m_Value != value) { m_Value = value; valueChange?.Invoke(m_Value); } } } public Action<int> valueChange; public int32(int value) { valueChange = null; m_Value = value; } public static explicit operator byte(int32 value) { return (byte)value.value; } public static explicit operator sbyte(int32 value) { return (sbyte)value.value; } public static explicit operator short(int32 value) { return (short)value.value; } public static explicit operator ushort(int32 value) { return (ushort)value.value; } public static implicit operator int(int32 value) { return value.value; } public static explicit operator uint(int32 value) { return (uint)value.value; } public static implicit operator long(int32 value) { return value.value; } public static explicit operator ulong(int32 value) { return (ulong)value.value; } public static implicit operator float(int32 value) { return value.value; } public static implicit operator double(int32 value) { return value.value; } public static bool operator <(int32 lhs, int32 rhs) { return lhs.m_Value < rhs.m_Value; } public static bool operator <=(int32 lhs, int32 rhs) { return lhs.m_Value <= rhs.m_Value; } public static bool operator >(int32 lhs, int32 rhs) { return lhs.m_Value > rhs.m_Value; } public static bool operator >=(int32 lhs, int32 rhs) { return lhs.m_Value >= rhs.m_Value; } public int CompareTo(object obj) { return CompareTo(Convert.ToInt32(obj)); } public override string ToString() { return m_Value.ToString(); } public string ToString(string format) { return m_Value.ToString(format); } public string ToString(IFormatProvider provider) { return m_Value.ToString(provider); } public string ToString(string format, IFormatProvider provider) { return m_Value.ToString(format, provider); } public int CompareTo(int32 other) { if (m_Value == other.m_Value) { return 0; } else if (m_Value > other.m_Value) { return 1; } return -1; } public bool Equals(int32 other) { return m_Value == other.m_Value; } } |
方法2 给基础数据起一个别名
利用nameof语法糖来代替别名,比如我们先有一个模块类。nameof语法糖会在编译的时候替换成字符串,所以它没有额外性能开销。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class ViewMod { static ViewMod mod; public static ViewMod Get() { if (mod == null) mod = new ViewMod(); return mod; } public int m_Field; public int field { get { return m_Field; } set { //修改数据抛出事件 m_Field = value; Event.Dispatch(nameof(field), value); } } } |
监听模块类中数据被修改
1 2 3 4 5 6 7 8 9 10 11 |
var mod = ViewMod.Get(); //UI中监听变化 Event.AddListener(nameof(mod.field), (i) => { Debug.Log("change: " + i); }); //模块修改 mod.field = 200; |
Event就比较简单了,注意这里还需要补充RemoveListener方法,如果要考虑其他short long float double这些数据可以拓展成泛型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public class Event { public static Dictionary<string, Action<int>> events = new Dictionary<string, Action<int>>(); public static void Dispatch(string name, int value) { if (events.TryGetValue(name, out var action)) { action?.Invoke(value); } } public static void AddListener(string name, Action<int> action) { if (!events.TryGetValue(name, out var __)) { events[name] = action; } else { events[name] += action; } } } |
我个人觉得方法2好一些。
1.nameof绑定了数据与事件,这样改了一个另外一个必须要改,不会出现漏改的情况。
2.需要考虑重名的问题,可以拓展nameof进行拼接。
3.需要考虑List中数据的问题,可以拓展nameof进行拼接。
欢迎一起讨论MMVM在实际项目中的应用。
- 本文固定链接: https://www.xuanyusong.com/archives/4790
- 转载请注明: 雨松MOMO 于 雨松MOMO程序研究院 发表
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!
这个应该是MVVM数据绑定吧
MVVM的数据绑定以前前的uframe就做得还行了,就是效率差点
如果多个数据类 有相同名字的字段属性 是不是就不可以了
是的, 但是可以以模块类为基础获取类型做个拼接,一般同一个模块不会有两个相同字段属性,除非写了两个内部类,写两个一样的属性,但这种情况很少