When coding in Visual Basic, I'm able to define triggers to variables like: Whenever the value of the variable is changed, this triggers a function, which in turn changes the value of another variable. I wonder if there is a way to do the same in C#; that is, I want to define a trigger to a variable, fired every time when the value of that variable is changed.
Below code is how I do it in VB. When running this App, whenever a new user logs in, the App assigns the username like ActiveUserName = "SomeUserName", and this in turn automatically updates the FormMain.StatusLabelUserName.Text in the form. So, is there a way to achieve this trigger in C#?
Public Property ActiveUserName() As String
Get
ActiveUserName = FormMain.StatusLabelUserName.Text
End Get
Set(ByVal Value As String)
FormMain.StatusLabelUserName.Text = Value
End Set
End Property
I believe you're looking for Properties
private int localMember;
public int publicProperty
{
get
{
return localMember;
}
set
{
localMember = value;
//Do whatever you want here.
}
}
The "get" block is run any time you access the value. The "set" block is run any time you assign a value.
This is handled by raising events. This post describes how to do it well.
This is a simple property. Here's the C# syntax:
public string ActiveUserName
{
get { return FormMain.StatusLabelUserName.Text; }
set { FormMain.StatusLabelUserName.Text = value; }
}
Properties can work the same in C#
public string ActiveUserName
{
get{ return FormMain.StatusLabelUserName.Text;}
set{FormMain.StatusLabelUserName.Text = value; /*do more stuff here; */}
}
This can get rather messy and somewhat rigid however. You may consider using events to accomplish the same thing.
Use INotifyPropertyChanged event.
Properties and the set brackets.
INotifyPropertyChanged could be implemented for WPF databindings for exemple.
Related
This is a bit of a confusing scenario. Basically, I'm trying to set a button's color when I use setter for a private variable that I store its color in.
First off, I have a seperate window for customizing stuff. When I change the button color, I want to change every button in this window as well. I have it stored in a static variable in my main form class.
public static frm_custom customizer;
This is the setter for the variable in question.
private Color _buttonColor;
public Color buttonColor
{
get { return this._buttonColor; }
set
{
this.btn_input.BackColor = buttonColor;
this._buttonColor = buttonColor;
if (Application.OpenForms.OfType<frm_custom>().Count() == 1)
{
customizer.setButtonColor(buttonColor);
}
}
}
Strangely, it doesn't effect the color at all. Did I do something wrong?
Did I do something wrong?
Yes. Your setter is just fetching the existing property value:
this.btn_input.BackColor = buttonColor;
this._buttonColor = buttonColor;
You meant to use value, which is the implicit parameter name for the setter:
this.btn_input.BackColor = value;
this._buttonColor = value;
(Ditto for your if block, but it's hard to tell how that's meant to work as it's not valid C# at the moment.)
As a side note, I'd strongly urge you to start following .NET naming conventions, which include capital letters for properties - so ButtonColor rather than buttonColor.
I see here lot of similar question, but I still not find answer that help me in situation.
I have two frame(lets say FrameChild), one is "in" another(practically FrameChild is in this frame, lets say FrameMain).
When I insert all parameters in FrameChild and tap on button witch is on bottom of FrameMain I call method that return string...
Now when i get string i need to change textbox text in FrameChild
I have tray many way.
First idea was something like:
FrameChild frm = new FrameChild;
frm.textbox.text = "somestring";
But nothing happen.
Than i thing use some property.
in FrameChield:
public string setTicNo
{
set
{
textBox.Text = value;
}
}
in FrameMain:
FrameChild frm = new FrameChild;
frm.setTicNo = "somestring";
When i debbuging I get value, but textbox still is empty...
On the end I try to bind textbox text on setTicNo;
public string setTicNo
{
get
{
return setTicNo;
}
set
{
setTicNo = value;
}
}
Xaml:
Text = {Binding setTicNo, Mode=TwoWay,UpdateSourceTrigger=Explicit}
(here i try use more bindings, but every time i get infinite loop.
Please help , I not have more ideas..
Thanx
Did you try building a single view model and bind it to both frames, if it was passed by ref which is the default it will change the value once you do.
A side note implement a INOTIFYPROPERTYCGANGED in the View model
I have a slider that has it's value property tied to a dependency property. I need to know if the user has changed the value through the GUI. Unfortunately, the value of this slider is often changed via code and the "Value_Changed" event fires when that happens.
I know of two ways to go around this:
Create a boolean and change it to true each time in the code before changing the value, changing it to false afterwards, and then checking for this boolean in the Value_Changed event.
Wiring up keypress, click and dragstop events to the slider.
I'm just wondering if there's a better way to know if the user has changed the value via the UI?
I'd do it this way:
public bool PositionModifiedByUser
{ /* implement IPropertyChanged if need to bind to this property */ }
// use this property from code
public double Position
{
get { return m_position ; }
set { SetPropertyValue ("PositionUI", ref m_position, value) ;
PositionModifiedByUser = false ; }
}
// bind to this property from the UI
public double PositionUI
{
get { return m_position ; }
set { if (SetPropertyValue ("PositionUI", ref m_position, value))
PositionModifiedByUser = true ; }
}
SetPropertyValue is a helper that checks for equality and fires property change notifications if the value actually changes.
Possibly duplicate questions. Quick answer:
<Slider Thumb.DragCompleted="MySlider_DragCompleted" />
See also this post
But the answer from Anton is better +1
[BindableAttribute(true)]
public double Slider1Value
{
get { return slider1Value; }
set
{
// only bind to the UI so any call to here came from the UI
if (slider1Value == value) return;
// do what you were going to do in value changed here
slider1Value = value;
}
}
private void clickHalf(object sender, RoutedEventArgs e)
{
// manipulate the private varible so set is not called
slider1Value = slider1Value / 2;
NotifyPropertyChanged("Slider1Value");
}
I'm working on an existing class that is two steps derived from System.Windows.Forms.Combo box.
The class overrides the Text property thus:
public override string Text
{
get
{
return this.AccessibilityObject.Value;
}
set
{
if (base.Text != value)
{
base.Text = value;
}
}
}
The reason given for that "get" is this MS bug: http://support.microsoft.com/kb/814346
However, I'm more interested in the fact that the "if" doesn't work.
There are times where "base.Text != value" is true and yet pressing F10 steps straight to the closing } of the "set" and the Text property is not changed.
I've seen this both by just checking values in the debugger, and putting a conditional breakpoint on that only breaks when the "if" statement's predicate is true.
How on earth can "if" go wrong?
The class between this and ComboBox doesn't touch the Text property. The bug above shouldn't really be affecting anything - it says it's fixed in VS2005. Is the debugger showing different values than the program itself sees?
Update
I think I've found what is happening here.
The debugger is reporting value incorrectly (including evaluating conditional breakpoints incorrectly). To see this, try the following pair of classes:
class MyBase
{
virtual public string Text
{
get
{
return "BaseText";
}
}
}
class MyDerived : MyBase
{
public override string Text
{
get
{
string test = base.Text;
return "DerivedText";
}
}
}
Put a breakpoint on the last return statement, then run the code and access that property.
In my VS2005, hovering over base.Text gives the value "DerivedText", but the variable test has been correctly set to "BaseText".
So, new question: why does the debugger not handle base properly, and how can I get it to?
Use String.Compare for comparing strings. There are subtleties with strings. I cannot tell you why the if would fail, other than that your strings might not really be 'equal'
... and this just about wraps up my new question. Ah well.
I have a .xaml file and a .cs file that share value with Binding.
To make it simples, I have 1 button and 1 textbox. I want to button to be disabled when the textbox's text has no character.
Here is the two codes of the xaml for binding:
<TextBox Name="txtSend" Text="{Binding Path=CurrentText,UpdateSourceTrigger=PropertyChanged}"></TextBox>
<Button IsEnabled="{Binding Path=IsTextValid}" Name="btnSend">Send</Button>
The two properties in the .cs file look like that:
public string CurrentText
{
get
{
return this.currentText;
}
set
{
this.currentText = value;
this.PropertyChange("CurrentText");
this.PropertyChange("IsTextValid");
}
}
public bool IsTextValid
{
get
{
return this.CurrentText.Length > 0;
}
}
The this.PropertyChanged is simply a method that call PropertyChanged from INotifyPropertyChanged.
The problem is that I have to call the this.PropertyChange("IsTextValid"); in the Setter of the CurrentText to be able to have the button state change.
Question 1) Is it the good way to do it... if the rules become more complexe I might require to call a lot of PropertyChanged...?
Question 2) My button is enable when the form load. How can I make it check the method from the start?
Question 1: This is correct. There is no problem doing that. However you could take a look at the validation using the IDataErrorInfo. (Google search for it, and you will find a lot of good examples)
Question 2: make sure your "currentText" string is initialized with string.empty. Because if you did not initialized it, it will be null, and the getter for IsTextValid will throw an exception, and WPF will fail to retrieve the value.
Or do it like that:
public bool IsTextValid
{
get
{
return ! string.IsNullOrEmpty( this.CurrentText );
}
}
Your way of doing it is correct. If you are a bit lazy (as I am), you should have a look on the NuGet package Fody.PropertyChanged.
Your code would simplify to
public string CurrentText { get; set; }
public bool IsTextValid { get { return this.CurrentText.Length > 0; } }
Fody.PropertyChanged does the rest for you. It automatically adds the needed instructions to notify that CurrentText changed, and it even detects that IsTextValid depends on CurrentText and notifies for it, too.