How can I do Databinding in c#? - c#

I have the following class
public class Car
{
public Name {get; set;}
}
and I want to bind this programmatically to a text box.
How do I do that?
Shooting in the dark:
...
Car car = new Car();
TextEdit editBox = new TextEdit();
editBox.DataBinding.Add("Name", car, "Car - Name");
...
I get the following error
"Cannot bind to the propery 'Name' on the target control.
What am I doing wrong and how should I be doing this? I am finding the databinding concept a bit difficult to grasp coming from web-development.

You want
editBox.DataBindings.Add("Text", car, "Name");
The first parameter is the name of the property on the control that you want to be databound, the second is the data source, the third parameter is the property on the data source that you want to bind to.

Without looking at the syntax, I'm pretty sure it's:
editBox.DataBinding.Add("Text", car, "Name");

editBox.DataBinding.Add("Text", car, "Name");
First arg is the name of the control property, the second is the object to bind, and the last, the name of the object property you want to use as the data source.

You are quite close the data bindings line would be
editBox.DataBinding.Add("Text", car, "Name");
This first parameter is the property of your editbox object that will be data bound. The second parameter is the data source you are binding to and the last parameter is the property on the data source that you want to bind to.
Bear in mind that the data binding is one way so if you change the edit box then the car object gets updated but if you change the car name directly the edit box is not updated.

Try:
editBox.DataBinding.Add( "Text", car", "Name" );

Using C# 4.6 syntax:
editBox.DataBinding.Add(nameof(editBox.Text), car, nameof(car.Name));
if car is null, then the above code will fail in a more conspicuous way than using literal string to represent the datamember of car

I believe that
editBox.DataBindings.Add(new Binding("Text", car, "Name"));
should do the trick. Didn't try it out, but I think that's the idea.

You're trying to bind to the "Name" of the TextEdit control. The name is used for accessing the control programmatically, and cannot be bound against. You should be binding against the Text of the control.

The following is generic class that can be used as a property and implements INotifyPropertyChanged used by bound controls to capture changes in the property value.
public class NotifyValue<datatype> : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
datatype _value;
public datatype Value
{
get
{
return _value;
}
set
{
_value = value;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Value"));
}
}
}
It can be declared like this:
public NotifyValue<int> myInteger = new NotifyValue<int>();
and assigned to a textbox like this
Textbox1.DataBindings.Add(
"Text",
this,
"myInteger.Value",
false,
DataSourceUpdateMode.OnPropertyChanged
);
..where "Text" is the property of the textbox, 'this' is current Form instance.
A class does not have to inherit the INotifyPropertyChanged class. Once you declare an event of type System.ComponentModel.PropertyChangedEventHandler the class change event will be subscribed to by the controls databinder

it's
this.editBox.DataBindings.Add(new Binding("Text", car, "Name"));

Related

Accessing the DataGridView Control on setting Property for Custom DataGridViewColumn

can some help me on how can I find the DataGridView control in the property setter of a Custom DataGridViewColumn. My code below is returning null. I want to get the parent DataGridView of my custom column.
public class CustomComboBoxColumn : DataGridViewComboBoxColumn
{
public string SomeProperty
{
get { return _SomeProperty; }
set
{
_SomeProperty = value;
CustomDataGridView dgv = this.DataGridView; //this one is returning null
}
}
}
The DataGridView (in WinForms - judging from the post tag) is a property of the DataGridViewColumnCollection Class - and not that of the DataGridViewColumn Class So since you are deriving this class from the
DataGridViewColumn derived class, you would have to make this property trickle down from the custom column collection to each of the custom columns added to it, perhaps you can make the collection itself accessible in each added column by implementing a Column.Collection custom property, and initializing it each time you add a column to a Collection. Then you can use inside your CustomComboBoxColumn class something alike this:
CustomDataGridView dgv = this.CustomComboBoxColumnCollection.DataGridView;
.
Alternativelly, consider to do what you were intending to do in CustomComboBoxColumn class in the collection that contains it instead. In the Collection you can access the CustomComboBoxColumnCollection.DataGridView property, and subsequently set the needed results at the time that you are adding the new Columns into the Collection.
Do what feels more natural to you and requires less coding :)

Dotvvm run-time binding to 'object' type

i have this class
public class Property{
public string Name {get;set;}
public object Value {get;set;}
}
i want to create list of the above class List<Property> and dynamically add Mark Up Controls Code only
, so as their website they have an example HERE and what i did to that example is adding a public property of type Property to the TextBoxWithLabel class and changed the setter of the above example for binding as follows:
[MarkupOptions(AllowHardCodedValue = false)]
public string Text
{
get { return (string)GetValue(TextProperty); }
set {
SetValue(TextProperty, value);
Property.Value = value;
}
}
public static readonly DotvvmProperty TextProperty
= DotvvmProperty.Register<string, TextBoxWithLabel>(c => c.Text, "");
when i run the app and type something in the input field, the Value property of Type Property still null and here is where i'm stuck
i tried also to debug setter and it turns out it does not reach there so there is problem with run-time binding, which is 'as their example' this line of code
textBox.SetBinding(TextBox.TextProperty, GetValueBinding(TextProperty));
any help will appreciated :)
EDIT:
for more clarification,i have page called MainAppPage
and Markup Control with code behind called ContentControl
simply , MainAppPage passes List<Property> to ContentControl using this in MainAppPage
<controls:ContentControl Instance="{value: ClassObject}"/> then ContentControl start iterating through List<Property> and creating InputField's that derive from HtmlGenericControl
InputField's rendering like a charm in ContentControl
only thing is not working is binding , so again, how to bind Property.Value to InputField.Text so any changes happens in UI from user reflects on Property.Value after the InputField gets unfocused like any other MVVM pattern ?
DotVVM does not assign to the property usning the setter, is sets the underlying property store in DotvvmBindableObject instead. It's very simmilar what WPF does with their DependencyProperty, it's needed to represent the data bindings. You can actually completely omit the C# property declaration, declaring the field TextProperty and calling the DotvvmProperty.Register is enough to declare a property for dotvvm.
Other "problem" is that the controls do not store any data, everything has to be persisted in the view model. You can only use the control properties to data-bind a view model property. I think we are running here into a XY problem, I can only tell why your code does not work, but I have no idea what are actually trying to do...
Anyway, if you just want to "bind" your control to a view model property, have a look at https://www.dotvvm.com/docs/tutorials/control-development-markup-controls-with-code/2.0. You can declare the property like that:
[MarkupOptions(AllowHardCodedValue = false)]
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DotvvmProperty TextProperty
= DotvvmProperty.Register<string, TextBoxWithLabel>(c => c.Text, "");
Use it in the markup of you control
#baseType FullName.Of.YourControl
{{value: _control.Text}}
And use the control in your page (or other control)
<cc:YourControl Text="{value: _this.Property.Value}" />

"Binding" wpf Combox selectedValue to an integer?

I just started a new wpf project in hopes that I could learn a new technique as opposed to using winForms all the time.
I seem to be having way too much difficulty binding the selected value of a comboBox to an integer variable in my "MainWindow" class.
I have been looking at a host of "simple" examples from sites like codeproject, but they all seem way too complicated to just return the selected value of a comboBox. I am used to setting the "SelectedValueChanged" property and just setting a variable, which takes just a few clicks, like so:
public int value;
public void comboBox_SelectedValueChanged()
{
value = comboBox.SelectedValue();
}
Is there a similarly sweet, simple, and short way to properly "bind" the selected comboBox item to an integer?
I am trying to understand how to use INotifyPropertyChanged but I keep getting errors when I try to use it. This is what I have so far, but to be honest, I'm not sure where I am going with it:
// Combo Box Value
public class ComboValue
{
#region Members
int valueToReturn;
#endregion
# region Properties
public int numWeeks
{
get { return valueToReturn; }
}
#endregion
}
// Veiw Model Class
public class ComboValueViewModel:INotifyPropertyChanged
{
#region Construction
public ComboValueViewModel()
{
}
#endregion
}
and I've never used "#region" before, I have no clue what that is.
Could someone fill me in if I'm headed down the right path here?
You don't mention how much you know of MVVM but here goes. Your view will have an associated ViewModel class. In here you'll expose a property containing the items to bind to the combobox, e.g.:
public List<ComboValue> ComboItems { get; set; }
If you populate this property in the VM's constructor, then a List<> is probably sufficient; however you'll often see an ObservableCollection<> used for this kind of thing - this comes into its own if you need to add or remove items within your VM code - your view will react to such changes and update the list accordingly. This won't happen with a List<>.
As for INotifyPropertyChanged, I haven't implemented this pattern in the above code snippet. Again, it's not strictly necessary if you populate the collection in the VM constructor and won't be re-assigning that property again. However it's good practice to use the INPC pattern on your VM properties. Without it, if you were to reassign that property elsewhere in your code, e.g.:-
ComboItems = aNewListOfItems;
then the view wouldn't be made aware of the property change, and the ComboBox wouldn't update. If you need this to happen then implement the INPC pattern on the property, e.g.:-
public List<ComboValue> ComboItems // or ObservableCollection<ComboValue>
{
get
{
return _comboItems;
}
set
{
if (_comboItems != value)
{
_comboItems = value;
OnPropertyChanged("ComboItems");
}
}
}
As you are working with a ComboBox, your VM should also expose a property that you bind to the control's SelectedItem property. This property should implement INPC, e.g.:-
public ComboValue SelectedItem
{
get
{
return _selectedItem;
}
set
{
if (_selectedItem != value)
{
_selectedItem = value;
OnPropertyChanged("SelectedItem");
}
}
}
As you select items in the combo, the VM's SelectedItem property will change to reflect the current selection.
Finally, your XAML should end up looking something like this:-
<ComboBox ItemsSource="{Binding ComboItems}" SelectedItem="{Binding SelectedItem}" />
Hope this gives you a little "primer" into WPF binding! (Code snippets taken from memory so may not be 100% correct!).
Edit
Your ComboValue class exposes a numWeeks property. As it stands, you'll probably find that your ComboBox displays a list of ComboValue type names. To get the number to appear, the easiest thing is just to override .ToString() in your class and return the value of numWeeks. For more advanced formatting of items in controls such as this, you'll typically specify an ItemTemplate (again, plenty of examples can be found via Google!).

When do I need to use automatic poperties and when properties with propertychanged event?

I am using wpf and its C sharp!
I have this in my Animal.cs clas
private string _animalName;
public string AnimalName
{
get { return _animalName; }
set
{
if(_animalName!= value)
{
_animalName= value;
this.NotifyPropertyChanged("AnimalName");
}
}
}
I could also write:
public string AnimalName {get;set;}
There is no difference in binding and validation. Everythings works as before when I exchange the code.
Is this due to the fact that I only create new animals but I do not allow to update the animals name in my application ?
So I need to call the propertyChanged("AnimalName"); only when I want to change its property value?
I am a c# beginner ;)
If your object has an updateable property (setter) that will be bound to a control then you need to ensure to let the bound control know of any changes to that property via INotifyPropertyChanged. However, if you have a readonly property and/or a property that's not going to be used in a data-binding scenario then you don't care about implementing or calling NotifyPropertyChanged method from within that property's setter in which case you can use automatic properties.

WPF - Binding in XAML to an object created in the code behind

Can an object created in the code (ie C#) be used for binding in the XAML?
For example:
public class MyForm
{
private MyComplexObject complexObject;
public MyForm()
{
InitializeComponent();
}
public OnButtonClick(object sender, RoutedEventArgs e)
{
complexObject = new MyComplexObject();
}
}
complexObject is not created till a button is clicked. But once that button is clicked I would like to have a text box that is bound to complexObject.ID start showing the Id.
I would like to do that in the XAML if that is possible.
Can this be done? If so, how?
Yes, this can be done, binding to a property that you update with the desired value. I'd suggest you look into the MVVM pattern (Model-View-ViewModel), which is really useful for structuring this nicely working with WPF. Check out this video for a nice overview:
MVVM video
Using MMVM you would create a class which would be the ViewModel class. This one would typically be set to the DataContext of the View. Having done so you could add dynamic references to the other properties of the class, e.g. binding your text field to some property holding the Id og the ComplexObject. If your ViewModel class had a property ComplexObject, which again had a property ID you'd simply bind to the object like this:
<TextBlock Text="{Binding ComplexObject.ID}" />
Having this you could trigger creation of your ComplexObject from mouse click, which you should ideally set up as a command binding. Also note that the ViewModel class (or whoever is holding the ComplexObject needs to notify the View when the object has been set. This can either be done by making the ComplexObject a DependencyProperty or by making the class holding the property implement the INotifyPropertyChanged interface - giving it the PropertyChanged function to trigger the changed event. I prefer the latter.
One possibility would be to have your XAML bind to a property on your code behind. The getter for that property would return complexObject.ID, if complexObject != null. Otherwise, it returns something "default", whether that's null or 0 or default(ID's type). Similarly, the setter for that property would assign value to complexObject.ID if complexObject is, again, not null.
public int ID
{
get
{
if (complexObject != null)
return complexObject.ID;
return 0; // or null or some appropriate default
}
set
{
if (complexObject != null)
complexObject.ID = value;
}
}

Categories

Resources