How to block assign value in setter in WPF - c#

I have for example property like this:
private string foobar;
public string Foobar
{
get
{
return this.foobar;
}
set
{
if (value != this.foobar)
{
// here I want to check if value is correct
if(value != something)
{
this.foobar = value;
this.NotifyPropertyChanged("Foobar");
}
else
{
value = null;
this.foobar = null;
this.NotifyPropertyChanged("Foobar");
}
}
}
}
Property is binded (MVVM) to Listview :
SelectedItem="{Binding Foobar, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}
.
And when user changes value in list, selecteditem is changed and value is set in setter. I code is ok, when user selected incorrect value, to value and foobar null is assigned. But in WPF still selected value is displayed. When I set breakpoint in getter I can see that it return null too. How to refresh WPF to clear selected value in listview ? It shoud be empty like at the begin.
Thanks

The problem with your code is that you want to override value assigned by binding in your setter method. This will not work because control will not update on next property change for simple reason that it has invoked it by setting property. To implement validation on your values try this build in mechanism.

i would prefer using IDataErrorInfo and dont use property setter logic. the main advantage is that your property value in your viewmodel and your view are always the same and your viewmodel has the information wether the value is ok or not.

Related

Distinguish if the user or the program changed a value in a wpf datagrid

i have a mvvm application in which i have a DataGrid in Wpf and want to get notified if a user changes a value in a column.
All dataGridColumns have a binding to my viewmodel, which invokes a PropertyChanged Command if it gets changed. Now the Problem is, how i can determine if the property has been changed by the user or by the code? Because i only want to add a note to the corresponding line when it has been changed manually by the user.
The Column of interest is implemented like this in wpf:
<DataGridTextColumn
Header="DIL"
Binding="{Binding DilutionFactor, StringFormat={}{0:n4}}"
Visibility="{Binding Value,
Source={StaticResource DilVis},
Converter={StaticResource BooleanToVisibilityConverter}}"
IsReadOnly="False"/>
Which is bound to the ViewModel Property:
public double DilutionFactor
{
get { return _dilutionFactor; }
set
{
_dilutionFactor = value;
Update(); // PropertyChanged Command
UpdatePipetteVolumes(); // function to update corresponding volumes
}
}
Is there a event or anything i can use to trigger a method when the user changes the value of the DIL column, which is not triggered when the code updates the value?
You could set a boolean flag each time before you programmatically change the value. Then in the property setter you can check that property to see if the user invoked the change. However, this method might need a lot of code changes for heavily used properties.
Another way:
Add a second property which just sets and returns the existing property. Then use that new property for the datagrid binding:
public double DilutionFactorUser
{
get { return this.DilutionFactor; }
set
{
this.DilutionFactor = value;
// Here comes the code that is only executed on user-invoked changes
}
}
public double DilutionFactor
{
get { return _dilutionFactor; }
set
{
_dilutionFactor = value;
Update(); // PropertyChanged Command
UpdatePipetteVolumes(); // function to update corresponding volumes
}
}
Set up your Datagrid to bind to DilutionFactorUser
You could also use the DataGrid.CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) event instead of looking the Property. e.Row.Item will have the data you are binding to.

Viewstate set Property value

I use viewstate in application where I have found that encapsulating viewstate in property is much more convenient.
Here is the code what I do in my code.
public List<TransactionEntity> TransactionData
{
get
{
if(ViewState["TransactionData"] == null)
return new List<TransactionEntity>();
return _TransactionData as List<TransactionEntity>();
}
set
{
How to set value to gridview from here ??
}
}
Now i have a gridview in user control which I need to bind everytime I assign value to this property.
Anyone knows how to do it.
Thanks.
Now i have a gridview in user control which I need to bind everytime I
assign value to this property.
Anyone knows how to do it
set
{
ViewState["TransactionData"] = value;
gridview.DataSource = value as List<TransactionEntity>; //check if null etc
gridview.DataBind();// ...
}

wpf binding with different source and target

Is is possible to make a binding in WPF whereas the source and target are different properties.
A la something like
Binding="{Binding Source=MySourceProperty, Target=MyTargetProperty}"
As requested an explanation of what I need to do:
The program among other things allows editing of properties that are part of a primary key in the database. If the property just gets changed, then this will either not update the DB value or create a duplicate, depending on how I handle saving the object. A different target would allow this to work (by explicitly specifying what to update by using the 'old' value).
A Binding defined in XAML is always targeting the object and property on which it's defined.
If you define the Binding in code, you can/must specify the source and target explicitly. This is, essentially, how the Binding class works:
Binding binding = new Binding("SourceProperty"); // Sets up the source property
myBinding.Source = mySourceObject; // sets up the source object
targetProperty.SetBinding(TargetType.TargetDepProperty, binding); // This sets the target object/binding
The XAML markup extension for a binding takes care of setting up the target side of the equation automatically, so it's always the object on which you define the binding.
I'll try to answer WHAT you need instead of asked incorrect HOW
"If the property just gets changed, then this will either not update
the DB value or create a duplicate"
In your property setter you should check set { if (this.someMember != value) if the typed in value is has changed:
public event PropertyChangedEventHandler PropertyChanged;
private string someMember;
public int SomeProperty
{
get
{ return this.someMember; }
set
{
if (this.someMember != value)
{
someMember = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("SomeProperty"));
}
}
}
As aside-note (or off-topic),
you might find useful the codeproject DataContext in WPF article in its last Download the source code has a sample when updates of one VisualModel's property is reflected (synchronized with updates in the other VM's property)
Immediately after launch:
The text typed in the 1st textbox is reflected in the 2nd textbox and vice versa, the text typed in the 2nd textbox is reflected in the 1st.
The text typed in the 3d textbox is reflected in the 4th textbox (and in textblock content at bottom) and vice versa, the text typed in the 4th textbox is reflected in the 3d (and in textblock content at bottom) .
Note that the download is DataCotext Inner Objects.zip which is unzipped into directory and solution with name Bindingtoclassesstate
In the set of the public property you have access to the old value
key is the old value
value is the proposed value from the binding
you can reject the value that comes from the binding
private string key;
public string Key
{
get { return key; }
set
{
if (key == value) return;
// try data update
bool success = updateDB();
if (success) key = value; // only update if success
}
}
I would combine the above with validation to notify the user if a value was invalid.
Validation Class

Has the user changed the value through the UI, or was it changed by the dependency property?

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");
}

determine a textbox's previous value in its lost focused event? WPF

I have a textbox and have an onlostfocus event on it.
Inside the lostfocus method, is there a way I can determine if the user has actually changed the value in it?
i.e how do i get hold of any previous value in it?
Thanks
As with just about everything else in WPF, this is easier if you use data binding.
Bind the text box to a class property. By default, bindings update the source when the bound control loses focus, so you don't have to muck around with the LostFocus event. You then have access to both the new value and the value that the user entered in the property setter.
In the XAML it looks like this:
<TextBox Text="{Binding MyProperty, Mode=TwoWay}"/>
In the class it looks like this:
private string _MyProperty;
public string MyProperty
{
get { return _MyProperty; }
set
{
// at this point, value contains what the user just typed, and
// _MyProperty contains the property's previous value.
if (value != _MyProperty)
{
_MyProperty = value;
// assuming you've implemented INotifyPropertyChanged in the usual way...
OnPropertyChanged("MyProperty");
}
}
What comes to mind for me is a two stage approach. Handle the TextChanged event on the textbox and flag it. Then when the textbox OnLostFocus occurs you can simply check your flag to see if the text has been changed.
Here is a code snippet on how you could handle the tracking.
public class MyView
{
private bool _textChanged = false;
private String _oldValue = String.Empty;
TextChanged( ... )
{
// The user modifed the text, set our flag
_textChanged = true;
}
OnLostFocus( ... )
{
// Has the text changed?
if( _textChanged )
{
// Do work with _oldValue and the
// current value of the textbox
// Finished work save the new value as old
_oldValue = myTextBox.Text;
// Reset changed flag
_textChanged = false;
}
}
}
Store the original value somewhere. You could write a common component to store the value when it gets focus and compare the value when it loses focus. I've done this in ASP.NET and it works quite well.
Another way to solve this by databinding:
Bind the TextBox.Text to the property, that holds the inital value, but use a binding with
UpdateSourceTrigger=Explicit
Then, when the textbox loses focus, you can check the binding if source and target values differ, using this code snippet and evaluating the resulting BindingExpression:
BindingExpression be = tb.GetBindingExpression(TextBox.TextProperty);
Some more code can be found here:
http://bea.stollnitz.com/blog/?p=41

Categories