在我解释问题之前用一句话概括我的蜿蜒问题。我怎样才能这样做,如果我从我的词典中的一个键更新一个值,它将触发与该键/ TextBinding相关联的OnPropertyChanged方法,或者我应该以不同的方式这样做
我对WPF / MVVM数据绑定有一些经验,所以梦想的解决方案适用于我的项目:如果我的游戏中的值发生变化,它将自动更新当前在UI上显示的任何位置。
我有一个非常基本的地方开始使用字典查找表,但可能有些人了解我需要哪些会更好用
第一个代码块是BindingBehavior,它可以被视为附加到UI文本字段(同一个父游戏对象的一个组件更加精确)
如果我将TextBinding设置为一个值,我的UI会更改以反映它,但是如果我通过我的字典更改一个值,那么我的字典似乎只保存了当时分配给它的值的副本,而不是更新引用“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");
}
}
以下是可读性的单独类
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());
答案 0 :(得分:0)
我认为您最好的选择是实施自己的ObservableDictionary
课程,该PropertyChanged
课程会在PropertyName
设置为"Item[]"
的情况下触发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));
}
事件。
这里有一个示例实现:http://blogs.microsoft.co.il/shimmy/2010/12/26/observabledictionarylttkey-tvaluegt-c/。关键部分是:
{{1}}
答案 1 :(得分:0)
我认为我有一个解决方案我很乐意在文本绑定的时候使用它虽然我将把它带到Unity Answers网站,看看是否有办法使用gameobjects做一个更通用的字典版本或组件或某些东西,这将是一个更“稳定”的解决方案。这是代码。事后看来,这似乎很明显,我不知道为什么我先试试这个。
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;
public class BindingBehavior : MonoBehaviour
{
public string BindingName;
public string TextInitialValue;
public Text TextComponent;
public string TextValue
{
get
{
if (TextComponent == null)
{
TextComponent = this.gameObject.GetComponent<Text>();
}
return TextComponent.text;
}
set
{
if (TextComponent == null)
{
TextComponent = this.gameObject.GetComponent<Text>();
}
TextComponent.text = value;
}
}
// Use this for initialization
void Start ()
{
TextValue = TextInitialValue;
UIManager.Instance.UITextBindings.Add(BindingName, TextComponent);
}
}
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
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, Text> UITextBindings = new Dictionary<string, Text>();
}
并更新我需要简单拨打电话的用户界面文字
UIManager.Instance.UITextBindings["ActiveCharacterActionPointsRemaining"].text = _activeCharacter.actionPointsRemaining.ToString();