c# - 数据绑定(bind),如 Unity 的行为

标签 c# dictionary unity3d

在解释问题之前用一句话总结我的曲折问题。我怎样才能做到这一点,如果我从我的字典中的一个键更新一个值,它将触发与该键/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/

相关文章:

javascript - 如何在 HttpHandler ProcessRequest 中获取字符串数组值?

ios - 无法快速访问 JSON 数组

Python - 从键列表访问分层字典元素

unity3d - Firebase Unity SDK : 100% hang on iOS when the application resumes

c# - 重力和向心力

C# XML 查找第一个元素后代

c# - 回滚后提交事务会发生什么?

c# - 如何获取和安装根 CA 证书

dictionary - 如何在Go中使用空结构值制作 map

android - Unity3d 中的 Google Cardboard 演示 : How to center a 3D object in your field of vision by double tapping touchscreen?