我一直在尝试为WinForm中的两个标签进行绑定工作,但我似乎无法弄清楚我做错了什么。目前,我正在实现INotifyPropertyChanged
接口,并将其绑定到表单中的几个属性。这影响的当前类是SessionForm.cs
,实际形式,Session.cs
,我保存程序的所有信息的地方。有问题的标签,在两个类中都没有提到,是L_No,它包含音乐标尺中Note的数字参考,L_Note,它包含内脏Note值(例如C,C#等)。
请允许我解释一下课程中的所有内容。该程序旨在通过根据您选择的比例询问您对比例的n th 注释来测试您的比例知识。您可以使用表单上的按钮进行选择。
这些选项记录在Session类中,已编辑该类以使其更简洁。整数数组包含与scale数组相关的音符索引,该数组位于Scale
对象中。例如,典型的Note
数组可能包含以下值:{1,3,0,2,6,1,3,...}
。通过使用Scale
对象中的数组作为参考,这些将转换为音符(例如D,F,C,E,B,D,F,......)。玩家的选择存储在NoteData
个对象的数组中。
在SessionForm.cs
我随着时间的推移操纵这些信息。每次做出或不做出选择时(取决于他们是否试图及时猜测),两个标签的值都会改变:L_No和L_Note。这两个标签分别由变量NoteIndex和LastNote操纵。当这些值发生变化时,会发生NotifyPropertyChanged,然后标签应更新......但他们没有这样做。
现在,在表单的设计部分,在“属性”窗口中,我将每个Label的Text属性设置为绑定到表单中各自的变量,并设置为在属性更改时更新,但似乎没有工作。
那么我做错了什么?
Session.cs :
public class Session
{
public struct NoteData
{
public int Note;
public bool Correct;
public int GuessTime;
}
public Scale Scale;
/// <summary>
/// Holds the notes for one game
/// </summary>
public int[] Notes { get; private set; }
public NoteData[] Data { get; private set; }
/// <summary>
/// Creates a Session
/// </summary>
/// <param name="difficulty">The difficult of the session, refer to the Resources Class for determination.</param>
/// <param name="scale_used">The scale to be used. Refer to the Resources Class for determination.</param>
/// <param name="notes">The notes being used within this Session</param>
public Session(Resources.Difficulties difficulty, Scale scale_used, int[] notes)
{
ID = DateTime.Now;
Diff = difficulty;
Scale = scale_used;
Notes = notes;
Data = new NoteData[notes.Length];
internalIndex = 0;
}
/// <summary>
/// Stores Note input for each guessed
/// </summary>
/// <param name="index">The index of the note the player is currently on</param>
/// <param name="correct">Was the guess correct?</param>
/// <param name="remaining_time">How long did it take for them to guess?</param>
public void StoreNoteInput(int index, bool correct, int remaining_time)
{
if (internalIndex < Data.Length)
Data[internalIndex++] = new NoteData(index, remaining_time, correct);
}
}
SessionForm.cs :
public partial class SessionForm : Form, INotifyPropertyChanged
{
public Session curSession { get; private set; }
Resources.Notes last_note;
/// <summary>
/// The note index number in relation to the scale
/// </summary>
public int NoteIndex
{
get
{ return note_index; }
private set
{
if (note_index != value)
{
note_index = value;
NotifyPropertyChanged("NoteIndex");
}
}
}
/// <summary>
/// Represents the previous note being tested
/// </summary>
public Resources.Notes LastNote
{
get
{
return last_note;
}
private set
{
if (last_note != value)
{
last_note = value;
NotifyPropertyChanged("LastNote");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void TickDownTimer_Tick(object sender, EventArgs e)
{
remainingTime -= countingDown ? 1000 : 100;
if (remainingTime == 0)
{
if (countingDown)
{
countingDown = false;
TickDownTimer.Interval = 100;
}
if (curIndex > 0)
{
//you ran out of time on the last note
RecordNoteInput(curIndex - 1, false);
}
NextNote();
}
SetTimerText();
}
private void RecordNoteInput(int index, bool correct)
{
curSession.StoreNoteInput(index, correct, remainingTime);
NoteIndex = curSession.Notes[curIndex - 1];
LastNote = curSession.Scale.Notes[NoteIndex];
L_Note.ForeColor = correct ? Color.Green : Color.Red;
}
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
更新:这是来自SessionForm.Designer.cs
的绑定代码:
this.sessionFormBindingSource1 = new System.Windows.Forms.BindingSource(this.components);
this.sessionFormBindingSource2 = new System.Windows.Forms.BindingSource(this.components);
this.sessionFormBindingSource = new System.Windows.Forms.BindingSource(this.components);
//
// L_Note
//
this.L_Note.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.sessionFormBindingSource1, "LastNote", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged, "C"));
this.L_Note.Text = " ";
//
// L_No
//
this.L_No.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.sessionFormBindingSource2, "NoteIndex", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged, "1", "N0"));
this.L_No.Text = " ";
答案 0 :(得分:2)
问题在于您拨打NotifyPropertyChanged
的方式:
NotifyPropertyChanged("note_index");
和
NotifyPropertyChanged("last_note");
只需从这样的调用中删除字符串
NotifyPropertyChanged();
一切都应该没问题。
编辑:如果不是,那么您的绑定未正确初始化。证明:
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
namespace Tests
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new TestForm());
}
}
class TestForm : Form, INotifyPropertyChanged
{
public TestForm()
{
var label = new Label { Parent = this, Left = 16, Top = 16, AutoSize = false, BorderStyle = BorderStyle.FixedSingle };
label.DataBindings.Add("Text", this, "NoteIndex");
var timer = new Timer { Interval = 200, Enabled = true };
timer.Tick += (sender, e) => NoteIndex = (NoteIndex + 1) % 10;
}
int note_index;
public int NoteIndex
{
get { return note_index; }
private set
{
if (note_index != value)
{
note_index = value;
NotifyPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}