在解释问题之前用一句话总结我的曲折问题。我怎样才能做到这一点,如果我从我的字典中的一个键更新一个值,它将触发与该键/TextBinding 关联的 OnPropertyChanged 方法,或者我应该以不同的方式执行此操作
我在 WPF/MVVM 数据绑定(bind)方面有一些经验,所以理想的解决方案适用于我的项目:如果我的游戏中的值发生变化,它将自动更新当前显示在 UI 上的任何位置。
我有一个非常基本的地方可以开始使用字典查找表,但可能有些人理解我需要的东西会更好
第一个代码块是 BindingBehavior,它可以被视为附加到 UI 文本字段(更准确地说是同一父游戏对象的组件)
如果我将 TextBinding 设置为一个值,我的 UI 会更改以反射(reflect)它,但如果我通过我的字典更改一个值,我的字典似乎只包含当时分配给它的值的副本,而不会更新引用“TextBinding”
编辑:我以某种方式丢失了一段文本,已修补
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;
public class BindingBehavior : MonoBehaviour
{
public string BindingName;
public string TextInitialValue;
private string _textBinding;
public string TextBinding
{
get
{
return _textBinding;
}
set
{
_textBinding = value;
NotifyPropertyChanged(value);
}
}
void NotifyPropertyChanged (string value)
{
this.gameObject.GetComponent<Text>().text = value;
}
// Use this for initialization
void Start ()
{
TextBinding = TextInitialValue;
UIManager.Instance.BindingLookUp.Add(BindingName, TextBinding);
Debug.Log (BindingName + ", " + TextBinding + " was added to Binding Lookup Dictionary");
}
}
Below is the separate class for readability
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System;
using System.Collections.Generic;
public class UIManager
{
private static UIManager _instance;
public static UIManager Instance
{
get
{
if (_instance == null)
{
_instance = new UIManager();
}
return _instance;
}
set
{
_instance = value;
}
}
public Dictionary<string, string> BindingLookUp = new Dictionary<string, string>();
}
编辑:第二次尝试使用从其他地方阅读的关于堆栈溢出的一些建议中的类(引用类型?)似乎仍然没有完成这项工作。
public class BindableString
{
private string _stringValue;
public string StringValue
{
get
{
return _stringValue;
}
set
{
_stringValue = value;
}
}
public BindableString(string s)
{
StringValue = s;
}
}
public class BindingBehavior : MonoBehaviour
{
public string BindingName;
public string TextInitialValue;
private BindableString _textBinding;
public BindableString TextBinding
{
get
{
return _textBinding;
}
set
{
_textBinding = value;
NotifyPropertyChanged(value);
}
}
void NotifyPropertyChanged (BindableString str)
{
this.gameObject.GetComponent<Text>().text = str.StringValue;
}
// Use this for initialization
void Start ()
{
TextBinding = new BindableString( TextInitialValue);
UIManager.Instance.BindingLookUp.Add(BindingName, TextBinding);
Debug.Log (BindingName + ", " + TextBinding + " was added to Binding Lookup Dictionary");
}
}
public class UIManager
{
private static UIManager _instance;
public static UIManager Instance
{
get
{
if (_instance == null)
{
_instance = new UIManager();
}
return _instance;
}
set
{
_instance = value;
}
}
public Dictionary<string, BindableString> BindingLookUp = new Dictionary<string, BindableString>();
}
这是我为更新文本所做的调用
UIManager.Instance.BindingLookUp["ActiveCharacterActionPointsRemaining"] = new BindableString(_activeCharacter.actionPointsRemaining.ToString());
最佳答案
我认为您最好的选择是实现您自己的 ObservableDictionary
类,该类触发 PropertyChanged
事件并将 PropertyName
设置为 ”项目[]”
。
这里有一个示例实现:http://blogs.microsoft.co.il/shimmy/2010/12/26/observabledictionarylttkey-tvaluegt-c/ .关键部分是:
private const string CountString = "Count";
private const string IndexerName = "Item[]";
private const string KeysName = "Keys";
private const string ValuesName = "Values";
private void Insert(TKey key, TValue value, bool add)
{
if (key == null)
throw new ArgumentNullException("key");
TValue item;
if (Dictionary.TryGetValue(key, out item))
{
if (add)
throw new ArgumentException("An item with the same key has already been added.");
if (Equals(item, value))
return;
Dictionary[key] = value;
OnCollectionChanged(NotifyCollectionChangedAction.Replace, new KeyValuePair<TKey, TValue>(key, value), new KeyValuePair<TKey, TValue>(key, item));
}
else
{
Dictionary[key] = value;
OnCollectionChanged(NotifyCollectionChangedAction.Add, new KeyValuePair<TKey, TValue>(key, value));
}
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> changedItem)
{
OnPropertyChanged();
if (CollectionChanged != null)
CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, changedItem));
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> newItem, KeyValuePair<TKey, TValue> oldItem)
{
OnPropertyChanged();
if (CollectionChanged != null)
CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItem, oldItem));
}
private void OnPropertyChanged()
{
OnPropertyChanged(CountString);
OnPropertyChanged(IndexerName);
OnPropertyChanged(KeysName);
OnPropertyChanged(ValuesName);
}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
关于c# - 数据绑定(bind),如 Unity 的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27772095/