EF object property changing - MVVM - c#

I have a viewmodel that has an EF object as one of its properties. The view has several text boxes wired up to that property via Text="{Binding Path=MyEFTable.Column1}". I'm using the MVVM Light toolkit so my viewmodels inherit ViewModelBase and subsequently each property calls RaisePropertyChanged() when changed.
I have noticed, however that changing MyEFTable.Column1 does not set off any changes in the viewmodel. I thought that EF objects tracked any changes, so I assumed that changing a column value in an EF object would cause the EF object itself to be changed. Is it no longer tracking changes since I am essentially copying the query result into a new MyEFTable object?

Does your bindable objects implement INotifyPropertyChanged or it's container, like ObservableCollection?
Are you rising the event?
Using a view model is only the start. First thing you should check is to see if the Column1 Property is being updated after the editing occurs. If a TextBox, the UpdateSourceTrigger default value is LostFocus. Maybe you can try change it to PropertyChanged.
If the value is updated in your MyEFTable.Column1 you're done. If not, again, something is using the INotifyPropertyChange.
Add more info and maybe the issue will be clearer.
HTH

Related

Reset Databinding automatically in winform C#

As all of us know, if we want to bind a control in the WinForm to a property It has to be done through the fallowing way:
txtTitle.DataBindings.Add(new Binding("Text", object, "Name", true, DataSourceUpdateMode.OnPropertyChanged))
but in this case if "object" ( second argument of the Binding) changes to another one, in order to reflect change in the UI, we have to reset binding in this way:
txtTitle.DataBindings.Clear();
txtTitle.DataBindings.Add(new Binding("Text", object, "Name", true, DataSourceUpdateMode.OnPropertyChanged))
but I'm looking for a solution that does the above code snippet automatically, without the need to do it manually.
I think BindingSource might help me because it has ResetBinding() method but I'm not sure.
I'll appreciate your guides.
Thank you in advance.
EDIT:
I know how to update UI element after changing property value by implementing INotifyPropertyChanged interface, but my question is how to deal with the situation when my object that UI control is bound to its property changes, not the property itself.
.
.
.
consider this situation. I have a list of objects of a class and I want to bind my textbox to the property of this class, but based on some situations I want to change my object that is selected from that list so textbox has to be updated to reflect the new object's property value. at the current stage the only solution I can use is to delete previous binding and add new one. I want that somehow UI element be aware of the situation and shows new object's property value automatically or with smallest code as possible.
Unless I'm really not understanding your use-case, all you need is a BindingSource object between your TextBox and data object.
You don't bind your TextBox directly to your object, but to the BindingSource. All you have to do is use the DataSource and DataMember properties of the BindingSource to "switch" which object is used as the source of data for your controls.
See: MS Docs

Binding UI-Element not Refresh by Change value in Itemsource

i'm new by programming in wpf and c#.
I have a litte problem with an datagrid.
The grid is binding on a EF-Table.
I can see and change all fields and save the changes to the database.
The problem is. When i save the data via context.savechanges to the SQL-Database, the Trigger on the SQL-Server-Table modified some fields in the record.
When is Reload the Entity for the currentItem after the save-command, i can see the modified data in my Entity but not in my UI.
I must make a datagrid.items.refresh to see the changes. But the refresh is not performant and i loose the current cell position.
I need a way, to push any changes from SQL-Server on the current record on the fly to the UI after change on field in the UI.
Have anybody some ideas?
In an simpel TextBox-Element on a Window, i can use the BindingExpression to push the changes via binding.UpdateTarget. But it's not possible in DatagridTextColumn.
Your entity class should implement the INotifyPropertyChanged interface and raise change notications whenever a data-bound property is set to a new value.
If you are using auto-generated entity classes, you need to modify the template that these are generated from:
How to get property change notifications with EF 4.x DbContext generator
Or you can bind to your own wrapper classes that do implement this interface:
Implement INotifyPropertyChanged on generated Entity Framework classes

WPF DataTrigger on PropertyChanged

I have a view model property that is set to runtime objects. I want to trigger an animation whenever this property changes, so I was planning to use DataTrigger. However, DataTrigger obviously has the requirement for a Value property--one that I don't know at design-time.
Is there a built in way to trigger an animation whenever a value changes, regardless of what it changes into?
I saw this question but I was wondering if there was anyway to do it purely in XAML. Otherwise I figure I could probably fire an event from my View Model whenever the property changes and listen to that.
One method would be to create a User Control with a dependency property and then bind both of your other properties to that i.e. one at compile time and the other at runtime. Alternatively you could use an Attached Behaviour to do the same thing.
Can add a boolean property and trigger the animation based on the bool property. Whenever the original property changes, set and reset the boolean property so that it triggers the animation and also goes back to default value for next notification.

How to forbid automatic databinding on validation error

I'm creating a simple database application in C# WPF using MVVM as Relay Commands and databinding. For in-memory storage of database content I use ObservableCollection, which is binded to the Datagrid as follows:
<DataGrid ItemsSource="{Binding Path=Softwares, Mode=OneWay}" SelectedItem="{Binding Path=SoftwareSelection, Mode=TwoWay}">
when the item is selected user can chose to edit it. For editation a form is opened with a bunch of textboxes with the data of given entity. All the fields are validated using IDataErrorInfo, unless all textboxes are valid, the ok button is not enabled, and therefore no changes can be saved to the collection and to the database.
Here is how the example textbox looks like:
<TextBox Text="{Binding Name, Mode=TwoWay, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"/>
But the tricky part is, in case I change some values in textboxes and then close the window, the new values are propagated to the ObservableCollection, which I don't want to. Do you have any idea, how to prevent such behaviour? I would like the databinding work only after clicking the button. Otherwise the databindng works well, so as the button (dis/en)abling and reflecting changes to the database and to the collection after clicking. Both views are serviced by different ViewModels, data between views are passed by firing events.
I tried to add to the DataGrid UpdateSourceTrigger=Explicit to the ItemsSource binding, but didn't help. Perhaps, I'm missing some application logic?
Thank you very much for your help.
This is where most WPF developers make mistakes of assumptions!
In MVVM dirty data can be stored in the ViewModel and that's what the layer of VM is for! It mimics the View from Model's perspective and because View is in error, the ViewModel would also be in the error. Thats perfectly valid.
So having said that, the question remains
How will you NOT allow the temporary / dirty data to flow to your
ObservableCollection?
Two ways...
If your ObservableCollection is specific to your model class (say MyItem) then if your Model class (MyItem) is an Entity class \ DAL class \ NHibernate class create a wrapper of MyItem class called ViewModelMyItem and then instead of ObservableCollection<MyItem> use ObservableCollection<ViewModelMyItem>.
This way dirty data from your View would be inside ViewModelMyItem and it can only be legitimately flown back to your model class (MyItem) ONLY when Save button is clicked. So that means in Save Command's Execute() delegate you can copy \ clone the ViewModelMyItem's properties into Item's properties, if validations in ViewModelMyItem are fine.
So if Item is an EntityType class / NHibernate class / WCF client model class, it would always only valid data as ViewModelMyItem is filtering the temporary / dirty information upfront.
You could use Explicit binding model. It stops the TwoWay data to flow back to the sorce Item unless BindingExpressions.UpdateSource() is explicitly called.
But according to me, this defeats MVVM in straightforward way because ViewModel will not have what UI is showing! Still however you can use *Attached Behavior * to govern explicit binding by staying in MVVM space!
Let me know if this helps!
You're better off putting the code into the domain object's property setter. Then synchronize with the visuals by triggering the NotifyPropertyChanged handler.
More on this topic:
http://msdn.microsoft.com/en-us/library/ms743695.aspx
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
Setting the Binding Mode to Explicit should require you to call the binding expressions UpdateSource() method to send changes back to your model. Because you only mentioned that you set Explicit on the DataGrid's binding, I'm guessing you only need to make sure that you have that mode explicitly set on any property that is being bound directly back to your model. Such as your TextBox's Text Binding, in the case above. That will likely fix your problem but require you to call UpdateSource() on each target's BindingExpression one way or another.
If you're using one of the mainstream ORM's (EF, Linq to SQL, etc), then chances are your Entities automatically implement INotifyPropertyChanged and INotifyPropertyChanging. Because you are sharing a reference to your single instance, all changes in your edit will be reflected in your main view and anything else Binding to that instance. As a dirtier alternative, you can just create a separate instance of the same type and manually copy the values back over when the window's dialog result is true.
The first approach requires you to manually update the bindings, the second approach requires you to manually update the values from the Edit's instance.
With some more code, I can help with your specific approach.

How to implement WPF ValueConverter that needs data from viewmodel?

i am writing an application that has a viewmodel and a usercontrol that displays
data from this viewmodel. The viewmodel contains an entity "Appointment", and those
appointments have a property "UserName".
When I display the appointments, I want to use a value-converter to get a color for
the user (depending on "UserName"), but the colors are not contained in the entity "Appointment", so I wanted to create a value-converter that uses the entity "User" from the viewmodel.
What is the best way to use another entity from the viewmodel inside the converter?
Is it possible to access the viewmodel from the usercontrol? I tried to place the converter inside my viewmodel-class, but can I access this class from the usercontrol?
I figured out that the following possibilities might work:
Adjust the viewmodel so that each appointment also contains the color. But I don't want to do this because I don't want to mess with the viewmodel.
Set the converter-parameter from the class that also contains the viewmodel at startup. (Does this work?)
Use x:Reference to databind the converter parameter to the viewmodel that is unknown at compile-time.(Is this possible?)
Converter parameter is the way to go.
Why is the viewmodel unknown at compile time?
Bindings are not compile time checked anyway.
Is the UserControl.DataContext being set to an instance of Appointment, you should be able to set the parameter to {Binding UserName} or {Binding Appointment.UserName} depending on exactly what you are setting as the DataContext on the UserControl.
I would suggest that you re-examine your reluctance to modify the view model. The purpose of having a view model in the first place is so that everything that the view needs can be found in one place. Coming up with elaborate value converters to prevent modifying the view model is an approach that gets increasingly unmaintainable the more you do it.

Categories

Resources