在其他类中使用windows窗体视图模型

本文关键字:windows 窗体 视图 模型 其他 | 更新日期: 2023-09-27 18:10:25

我尝试从ViewModel中读取属性,该属性绑定到windows窗体上的一些控件。我使ViewModel作为单例,所以我确信只有一个实例。问题是,当我去其他类,并获得ViewModel的单例实例读取它的属性,他们不等于这些在ViewModel类。下面是ViewModel类:

class EditorToolboxViewModel : INotifyPropertyChanged
{
    static EditorToolboxViewModel instance;
    public static EditorToolboxViewModel GetSingleton()
    {
        if (instance == null)
            instance = new EditorToolboxViewModel();
        return instance;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public int BrushRadius {get; set;}
    public int BrushSensitivity {get; set;}
    public bool TerrainUp { get; set; }
    public bool TerrainDown { get; set; }
    public bool AddTerrainSlot { get; set; }
    public bool RemoveTerrainSlot { get; set; }
    public bool FlattenTerrain { get; set; }
    public float FlattenTerrainTarget { get; set; }
    private EditorToolboxViewModel()
    {
        BrushRadius = 10;
        BrushSensitivity = 1;
    }
}

这是我如何将它绑定到windows窗体上的控件:

this.viewModel = EditorToolboxViewModel.GetSingleton();
this.trackBarBrushRadius.DataBindings.Add(new Binding("Value", viewModel, "BrushRadius"));
this.trackBarTerrainBrushSensitivity.DataBindings.Add(new Binding("Value", viewModel, "BrushSensitivity"));
this.radioButtonIncreaseHeight.DataBindings.Add("Checked", viewModel, "TerrainUp");
this.radioButtonDecreaseHeight.DataBindings.Add("Checked", viewModel, "TerrainDown");
this.radioButtonAddTerrainSlot.DataBindings.Add(new Binding("Checked", viewModel, "AddTerrainSlot"));
this.radioButtonRemoveTerrainSlot.DataBindings.Add(new Binding("Checked", viewModel, "RemoveTerrainSlot"));
this.radioButtonFlattenTerrain.DataBindings.Add(new Binding("Checked", viewModel, "FlattenTerrain"));
this.textBoxTerrainFlattenTarget.DataBindings.Add(new Binding("Text", viewModel, "FlattenTerrainTarget"));

现在,当我点击TerrainUp单选按钮并尝试从其他类的viewmodel读取值时,它仍然是false:

bool b = EditorToolboxViewModel.GetSingleton().TerrainUp;

在ViewModel类中,一切都是正确的,但是在其他地方访问它会导致数据不匹配。

任何想法?

在其他类中使用windows窗体视图模型

1)通过a ==比较检查对象是否相同。由于绑定了一个窗口,属性可能在不同的时间具有不同的值。如果你确认对象是相同的,你就知道Singleton正在工作,并且可能有一个绑定改变了属性值。

2) Singleton应该有一个私有字段,而不是一个内部字段。

你的Singleton不是线程安全的,所以检查一下。

我最终解决了我的问题。

看起来这是一个已知的bug,单选按钮在状态改变期间失去绑定,所以这就是为什么视图模型行为不正确。看这里:http://www.abhisheksur.com/2011/03/issue-with-radiobuttons-and-binding-for.html

一个可能的解决方案是用复选框代替单选按钮。但是这样做时,请记住两件事:

  1. 在viewmodel中设置所有的复选框绑定为false,然后在它应该在的地方设置为true(如果你想让复选框表现得像单选按钮)。
  2. 重要: ViewModel不是在单击复选框时被验证,而是在复选框失去焦点时被验证。因此,要在单击后强制视图模型验证,只需通过编程将焦点更改为表单上的其他控件,如下所示:

    void CheckBoxes_CheckedChanged(object sender, EventArgs e)
    {           
        CheckBox c = (CheckBox)sender;
        var otherCheckBoxName = typeof(EditorToolbox).GetRuntimeFields().Where(x => x.FieldType == typeof(CheckBox) && !x.Name.Equals(c.Name)).Select(x => x.Name).FirstOrDefault();
        CheckBox c2 = (CheckBox)this.Controls.Find(otherCheckBoxName, true).FirstOrDefault();
        c2.Focus();
    }