Set TextBox Text programmatically and update the model - c#

I'm updating a TextBox.Text value in C# but the model binded to wasn't updated.
When I update that visually it works (commenting this line myTextbox.Text="new value"; and inputing manually the value at runtime)
<TextBox Name="myTextbox" Text="{Binding myValue}"/>

I think you need to implement INotifyPropertyChanged.

In your view model you need to call notify of property changed for binding value.
private string _myValue;
public string MyValue
{
get { return _value; }
set
{
_myValue = value;
NotifyOfPropertyChanged("MyValue");
}
}

writing "new value" in your textbox(ui) its not the same as myTextbox.Text="new value" in your codebehind(c#)
so my firsst question would be why you need myTextbox.Text="new value"??

Related

C# WPF I cannot get private to update but public will

I am very puzzled about this and have searched but cannot find the answer. I am sure I have not understood something correctly. Can you please explain this to me?
I have a View and a ViewModel. In the view I have a Textblock
<TextBlock
Grid.Row="4"
Grid.Column="5"
Grid.ColumnSpan="3"
IsEnabled="{Binding Enable, Mode=OneWay}"
Margin="5,10,5,10">
<Run Text="File: "/>
<Run Text="{Binding FilePathName}"/>
</TextBlock>
At the top of the View I have
d:DataContext="{d:DesignInstance d:Type=viewModels:MainWindowViewModel}"
I also added in Code behind
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
I did not want to add the DataContext here but it seemed at first to make it work but now I am not sure I need it and I will try removing it.
I think I understand this part that the data in the View will be refreshed from the item called FilePathName in the ViewModel.
Now in the view model I have created the “get and set” for the FilePathName as:
private string _filepathname;
public string FilePathName
{
get => _filepathname;
set
{
if (_filepathname != value)
{
_filepathname = value;
OnPropertyChanged();
}
}
}
Now this is where my understanding must be going a bit hazy. I think that within the ModelView I will just use the private string. This means when I change its value like this:
_filepathname = “MyNewName”;
then the PropertyChanged will see this change and will update the View via the public FilePathName. However if I use the FileOpenDialog and open a file and then say
if (openFileDialog.FileName != "")
{
_filepathname = openFileDialog.FileName;
ProcessFile();
}
I am using the private here but this will never update. If I put a break point in the “get and set” we never go there so the UI never updates.
However in ProcessFile() I use
StreamReader sr = new StreamReader(_filepathname);
I do actually read the correct file. This I could understand as it is also private. BUT … if I now change the private to public as follows
if (openFileDialog.FileName != "")
{
FilePathName = openFileDialog.FileName;
ProcessFile();
}
I now update on the UI and open the correct file for reading. It seems sometimes I need to use private and sometimes public to make it work. Why?
A second question is why does isEnabled not seem to work on TextBlock. I have it working on buttons and Textbox. I use it in TextBlock as follows and you can see it further above.
IsEnabled="{Binding Enable, Mode=OneWay}"
All help appreciated.
This does not work like that.
If it was, why would we need properties?
This:
myString = "new value"
ONLY assignes value to variable. And that's all. When you do this using property, property setter will be called, so:
if(myString != value)
{
myString = value; //new value will be assigned to variable
OnPropertyChanged(); //property changed will be called
}
When you assign value to variable, then you can just read it and that's what happens.
This variable is called "backing field". It's there because there has to be some variable that stores a value. If you declare property like that:
public string MyString {get; set;}
under the hood, the compiler also creates such backing field and in the end it works like that:
string __myString;
public string MyString
{
get {return __myString;}
set {__myString = value;}
}
so, as you can see, this is just a synthatic sugar. If you want to get more out of properties (like call property changed), you have to create such bakcing field by yourself.
What's more, property doesn't store any value by itself. Think of it as it has been a method. Actually two methods - one that assigns value to variable and the other that returns the value:
public void SetMyString(string value)
{
myString = value;
}
public string GetMyString()
{
return myString;
}
Because property at all is also some kind of synthatic sugar.
So to sum up:
string myString;
public string MyString
{
get {return myString;}
set
{
if(myString != value)
{
myString = value;
OnPropertyChanged();
}
}
}
///
myString = "NewValue"; //<-- only assigns value to variable myString
MyString = "NewValue"; //<-- assings value to variable myString AND calls OnPropertyChanged - because that's how you property setter looks like.
Your view and view model are two different classes.
When you change a private field of your view model, your view has no way to know if it is not notified. You notify the view when you call OnPropertyChanged() in the property setter. The property setter is not called when you modifiy the field. Read Adam's anwser for more details.
To answer your second question, IsEnabled is not the property you are looking for, as it disables the UI element, but does not hide it. You need to change the Visibility property for that (with a converter).
Here is how I would do it (with other simplifications):
<!-- in application or control resources -->
<BooleanToVisibilityConverter x:Key="BooleanToVisibility" />
<TextBlock Grid.Row="4"
Grid.Column="5"
Grid.ColumnSpan="3"
Text="{Binding FilePathName, StringFormat=File: {0}}"
Visibility="{Binding Enable, Mode=OneWay, Converter={StaticResource BooleanToVisibility}}"
Margin="5,10"/>

C# Binding a Property but checking another [duplicate]

Is it possible to bind to a value in Properties.Settings.Default in a way that will keep my UI current with the value stored there?
I have a class:
public class FavoritePlayer
{
public string Name
{
get
{
return wpfSample021.Properties.Settings.Default.FavoritePlayer.ToString();
}
set
{
wpfSample021.Properties.Settings.Default.FavoritePlayer = value;
}
}
}
In my XAML, I have a resource:
<local:FavoritePlayer x:Key="fvPlayer"/>
and a binding:
<Label DataContext="{DynamicResource fvPlayer}" Content="{Binding Path=Name}"/>
What I would like is for the data-binding to update any time the property is changed. Is there a way to do this?
Conveniently for you, ApplicationSettingsBase implements INotifyPropertyChanged so you just need to subscribe to PropertyChanged on Properties.Settings.Default and raise your own PropertyChanged in response.
You need your properties to implement INotifyPropertyChanged in order for bindings to recognise when the property value changes.

Determine if Textboxes Contain Values MVVM

I have a WPF page which consists of multiple text boxes and a search button. When one presses the search button the program needs to enumerate all the controls to determine if at least one of the textboxes is filled. If all are empty error then an error will be shown. The mvvm-light pattern is being used.
How does one enumerate all the textboxes under MVVM
There's an easy way that you can achieve your goal.
You can create a ViewModel and create properties in this ViewModel, so you can bind these properties to your TextBox on XAML, doing so your properties on ViewModel will maintain the value of the textbox's, here's an example.
XAML
<TextBox Text="{Binding Name, Mode=TwoWay}"/>
<TextBox Text="{Binding Age, Mode=TwoWay}"/>
"Mode=TwoWay" means whenever the bind property change, the textBox will be updated automatically.
XAML Code behaind.
public MainWindow(){
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
You need set the DataContext in order to be able to bind the properties.
ViewModel
public class MainWindowViewModel{
private string _name;
public string Name{
get{
return _name;
}
set{
_name = value;
}
}
private int _age;
public int Age{
get{
return _age;
}
set{
_age = value;
}
}
}
That is it, everytime when you need to check if your TextBoxes are empty, you can do so checking if your properties on View Model are empty.
Follow this logic to enumerate the controls and inform the user of its status.
Bind each of the controls on the view to individual properties on the View Model.
Create a method on the ViewModel, maybe called AreAllBlank (?) to enumerate each of the properties checking whether they are blank or not. If they are all blank, return true, otherwise return false.
On the view, for the button press's code behind operation, call the method created in step 2. If the result shows that they controls do not have data call MessageBox.Show() with an appropriate message.

WPF: Binding TextBox Text to a sub-element of a Property with WCF?

I have a TextBox which I'm trying to bind to a element of a table property 'regimeAlias' is a column with the tbRegimes table which I have mapped with Entity Framework:
<TextBox Text="{Binding NewRegime.regimeAlias, Mode=TwoWay}"/>
Exposed property in my ViewModel:
private tbRegime _NewRegime;
public tbRegime NewRegime
{
get { return _NewRegime; }
set
{
_NewRegime = value;
OnPropertyChanged("NewRegime");
}
}
Lastly, here's the WCF Service Reference auto-generated code class:
public partial class tbRegime : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
//blah blah blah
[System.Runtime.Serialization.DataMemberAttribute()]
public string regimeAlias {
get {
return this.regimeAliasField;
}
set {
if ((object.ReferenceEquals(this.regimeAliasField, value) != true)) {
this.regimeAliasField = value;
this.RaisePropertyChanged("regimeAlias");
}
}
}
The setter never gets hit. Is this because each element within the NewRegime object needs to raise PropertyChanged and if so is there an easy workaround without adding a further DTO layer to my code?
Edit3: with the post from your regimeAlias code. i have to say your binding should work. but of course if you wanna debug you have to set the breakpoint in your regimeAlias setter
<TextBox Text="{Binding NewRegime.regimeAlias, Mode=TwoWay}"/>
this code means, you bind to a Public Property regimeAlias in your class tbRegime.
your setter for NewRegime will never hit because you dont bind to it.
so check your tbRegime class property setter for regimeAlias.
EDIT: the DataContext of the TextBox is of course an object with the Public Property NewRegime, but like i said if you use dot notation in your binding the last property is the one you bind to :)
EDIT: you dont have much ways to workaround:) if you let the binding like you did, you need a model with a public property regimeAlias and it should implement INotifyPropertyChanged.
if you wanna wrap the regimeAlias Property then you have the problem the you have to raise OnPropertyChanged("MyRegimeAlias") at the right point.
public string MyRegimeAlias
{
get { return _NewRegime.regimeAlias; }
set
{
_NewRegime.regimeAlias = value;
OnPropertyChanged("MyRegimeAlias");
}
}
xaml
<TextBox Text="{Binding MyRegimeAlias, Mode=TwoWay}"/>

WPF Data Binding TooWay XAML to C# and C# to XAML

I have XAML code:
<TextBox Name="textBoxMask1"/>
<TextBox Name="textBoxMask2"/>
<TextBox Name="textBoxMask3"/>
...
<TextBox Name="textBoxMask9"/>
and class in C#:
private static string mask1;
public static string Mask1
{
get { return mask1; }
set { mask1 = value; }
}
private static string mask2;
public static string Mask2
{
get { return mask2; }
set { mask2 = value; }
}
private static string mask3;
public static string Mask3
{
get { return mask3; }
set { mask3 = value; }
}
....
private static string mask9;
public static string Mask9
{
get { return mask9; }
set { mask9 = value; }
}
And I want to bind these TextBoxes with Properties -> textBoxMask1 with Mask1 etc.
Earlier I did this by TextChanged, but I want to make Binding. TooWay Binding, because I want to predefine Mask1, Mask2, Mask3, ..., Mask9 in another C# class, and maybe later change these values - also in some C# code - and I want my changes, to be visible in layout (XAML) and in C# code - so ex. changing Property Mask1 from C# will change Text in TextBox textBoxMask1, and changing Text in textBoxMask1 will change Property Mask1.
I don't understand, how to make connection (binding) between objects XAML and C#.
For a normal Binding you don't need your properties to be static, just public. Here an example:
C# code (for one property)
private string mask1;
public string Mask1
{
get { return mask1; }
set
{
mask2 = value;
RaisePropertyChanged("Mask1");
}
}
It's really important for the binding that the class containing the properties implements the INotifyPropertyChanged interface, and that you raise the corresponding event in the setter of each property. Another option is to make all properties DependecyProperty, but it is usually overkill.
As for the XAML:
<TextBox Name="textBoxMask1" Text="{Binding Mask1, Mode=TwoWay}"/>
(TwoWay Binding is the default for the Text property, but it does not hurt to put it explicitly).
Just make sure that the DataContext of the object containing your TexBoxes (usually an UserControl) is set to a valid instance of your C# class.
By the way, this is a very basic question, that's why you got a negative vote and no answers before mine. What is expected is that you ask a question that poses a real problem for you, with a very specific answer, not something like "teach me how to do this".
If this answers your question don't forget to mark it as answer (the "tick" mark on the top left). A vote up would be also appreciated.
Hope it helps, regards.

Categories