问题
I'd like to update a view from another view via events. At the moment I have no idea how to do that?.
My Case:
I have a calculation engine, and when I perform the calculation, I want to inform the user about the performed steps. So I open a new window with a RichTextBox
control to display the desired information. When a new step is performed, I want to raise an event in order to display the text in the other window (RichTextBox
).
Is there an example which can help me to do this?
回答1:
Basically it is always a good idea not to change views directly but to operate on a model or "ViewModel" instead. So here is what I suggest:
Define a ViewModel for the calculation:
public class CalculationViewModel
{
public event Action ResultChanged;
private string _result = string.Empty;
public string Result
{
get { return _result; }
set { _result = value; Notify(); }
}
private void Notify()
{
if (ResultChanged!= null)
{
ResultChanged();
}
}
}
Your view (the form you mentioned which displays the result) subscribes to that. It will have a property that can be used to set the model.
private CalculationViewModel _model;
public CalculationViewModel Model
{
get { return _model; };
set
{
if (_model != null) _model.ResultChanged -= Refresh;
_model = value;
_model.ResultChanged += Refresh;
};
}
public void Refresh()
{
// display the result
}
You'll have a piece of code that sticks the things together (you may call it a controller if you like):
var calculationModel = new CalculationViewModel();
var theForm = new MyForm(); // this is the form you mentioned which displays the result.
theForm.Model = calculationModel;
var engine = new CalculationEngine();
engine.Model = calculationModel;
This code creates the model, the engine and the view. The model is injected into the view as well as the engine. By that time the view subscribes to any changes to the model. Now when the engine is run, it saves the result to its model. The model will notify its subscribers. The view will receive the notification and call its own Refresh() method to update the text box.
This is a simplified example. Take it as a starting point. In particular, WinForms provides its own data-binding mechanism which you could leverage so instead of creating a piece of code called "Refresh" you'd bind your textbox to the model by using its DataSource property. This requires that you use the WinForm's own change notification mechanism as well. But I think that you need to understand the concept first before moving on to let this be done behind the scenes.
回答2:
Just added it without compile-check, beware of typo's.
public partial class Form1: Form {
protected void btnCalculation_Click(object sender, EventArgs e) {
var form2 = new Form2();
form2.RegisterEvent(this);
form2.Show();
OnCalculationEventArgs("Start");
// calculation step 1...
// TODO
OnCalculationEventArgs("Step 1 done");
// calculation step 2...
// TODO
OnCalculationEventArgs("Step 2 done");
}
public event EventHandler<CalculationEventArgs> CalculationStep;
private void OnCalculationStep(string text) {
var calculationStep = CalculationStep;
if (calculationStep != null)
calculationStep(this, new CalculationEventArgs(text));
}
}
public class CalculationEventArgs: EventArgs {
public string Text {get; set;}
public CalculationEventArgs(string text) {
Text = text;
}
}
public partial class Form2: Form {
public void RegisterEvent(Form1 form) {
form1.CalculationStep += form1_CalculationStep;
}
private void form1_CalculationStep(object sender, CalculationEventArgs e) {
// Handle event.
// Suppose there is a richTextBox1 control;
richTextBox1.Text += e.Text;
}
}
来源:https://stackoverflow.com/questions/12002820/update-view-from-another-view