【问题标题】:How can I make the value of a variable track the value of another如何使变量的值跟踪另一个变量的值
【发布时间】:2018-10-07 03:36:45
【问题描述】:

这是我现在拥有的一个非常简化的示例:

public static class Settings
{
    public static TH th;
}

public partial class PhrasesFrame
{
    private void SetC1Btn()
    {
        var a = (int)Settings.th;
        vm.C1BtnLabelTextColor = phrase.C1 == true ?
            Styles.A[(int)Settings.th] :
            Styles.A[(int)Settings.th];
    }

我想将其替换为:

public partial class PhrasesFrame
{
    // The value of Settings.th can change at any time

    // I want the value of id to change when the 
    // value of (int)Setting.th changes. The way
    // it's coded now I realize it's just a one
    // time assignment

    var id = (int)Settings.th; 

    private void SetC1Btn()
    {
        var a = (int)Settings.th;
        vm.C1BtnLabelTextColor = phrase.C1 == true ?
            Styles.A[id] :
            Styles.A[id];
    }

【问题讨论】:

  • public int Id; public function PhrasesFrame() { Id = (int) Settings.th; }?
  • 如果Settings(类?)可以实现INotifyPropertyChangePhrasesFrame 可以订阅它并在 ACK 时更改a 的值。
  • @FrankerZ - 抱歉,我不了解那里发生的事情。您正在创建一个函数,但我将在哪里使用它? PhrasesFrame 类是一次性创建的。在初始创建之后,Id 会不断更改以具有 (int) Settings.th 的值吗?
  • 啊,不。我没有注意到Settingsstatic。无法在此处实现接口。我会看看我能不能想出一些可行的办法。
  • 实现 INotifyPropertyChanged 或添加执行相同操作的自定义事件处理程序。这就是 WPF 和数据绑定的亮点。

标签: c# .net events


【解决方案1】:

这个Settings 类实现了一个自定义EventHandler (SettingsChangedEventHandler),用于通知其订阅者的属性更改:
您可以设置一个更复杂的自定义 SettingsEventArgs 来传递不同的值。

更改公共THProperty 属性值引发事件:

public static class Settings
{
    public delegate void SettingsChangedEventHandler(object sender, SettingsEventArgs e);
    public static event SettingsChangedEventHandler SettingsChanged;

    private static TH th;
    private static int m_Other;

    public class SettingsEventArgs : EventArgs
    {
        public SettingsEventArgs(TH m_v) => THValue = m_v;
        public TH THValue { get; private set; }
        public int Other => m_Other;
    }

    public static void OnSettingsChanged(SettingsEventArgs e) => 
        SettingsChanged?.Invoke("Settings", e);

    public static TH THProperty
    {
        get => th;
        set { th = value; OnSettingsChanged(new SettingsEventArgs(th)); }
    }
}

PhrasesFrame 类可以像往常一样订阅事件:

public partial class PhrasesFrame
{
    private TH id;

    public PhrasesFrame()
    {
        Settings.SettingsChanged += this.SettingsChanged;
    }

    private void SetC1Btn()
    {
        var a = (int)this.id;
        //Other operations
    }

    private void SettingsChanged(object sender, Settings.SettingsEventArgs e)
    {
        this.id = e.THValue;
        SetC1Btn();
    }
}

【讨论】:

  • 这是解决问题的简单有效的方法。它与 INotifyPropertyChanged 非常相似
  • @rolls 这就是目的。因为,在 cmets 中,我提出了一个事件处理程序......感谢您的反馈。
  • @Jimi - 我是否必须在任何时候销毁已添加到 PhrasesFrame 的事件,例如 PhrasesFrame 不再被引用?
  • @Alan2 会更好。 PhrasesFrame 可以在其Dispose() 方法中实现IDisposable 并取消订阅Settings.SettingsChangedDispose() 的结构取决于PhrasesFrame 实例化的托管/非托管资源。关于这个:Implementing a Dispose method。 Eric Lippert 臭名昭著的系列:When everything you know is wrong.
【解决方案2】:

如何将一个动作添加到您的静态设置类,并从设置器触发该动作?

我使用 int 代替您的 TH 对象,但我相信您可以修改以下示例。

在这里测试:https://dotnetfiddle.net/ItaMhL

using System;
public class Program
{
    public static void Main()
    {
        var id = (int)Settings.th;
        Settings.action = () => id = Settings.th;
        Settings.th = 123;
        Console.WriteLine(id);

        Settings.th = 234;
        Console.WriteLine(id);
    }

    public static class Settings
    {
        private static int _th;
        public static int th
        {
            get{return _th;}
            set{
                _th = value;
                action();}
        }

        public static Action action;
    }
}

【讨论】:

  • 如果他有 50 个设置会发生什么?一个简单的动作没有非常明确的意图。它也仅限于单个侦听器。事件处理程序是更好的选择。
  • 当然,你是对的。我专注于这个非常具体的例子,只有一个值。但是,是的,用 50 个值使用这种技术肯定会一团糟
  • 不是每个人都对一次传递更多参数感兴趣。这是处理单个属性值更改的好方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-19
  • 2018-10-06
  • 1970-01-01
  • 2023-03-17
  • 2022-01-10
  • 1970-01-01
相关资源
最近更新 更多