Problem: Cannot set backing field of property to private as I get the following exception when setting a value to Name.
System.ArgumentException : You must declare a
backing field for this property named: _Name
My Code:
public class MyVM : ReactiveObject
{
private string _Name;
public string Name
{
get { return _Name; }
set { this.RaiseAndSetIfChanged(x => x.Name, value); }
}
}
To Fix this i have been able to set _Name to public:
public string _Name;
Which fixed the problem, but why do I have to expose the backing field as public? The examples I see on the Net use private backing fields...?
Use the new overload instead, unless you're not using >= VS2012:
this.RaiseAndSetIfChanged(ref theBackingField, value);
Related
I am new to ObjectListView and I haven't found how to use a property of a object inside the model as AspectName for ObjectListView.
For example, the list will show Cars names and their owner name
public class Person
{
private string _name;
public string Name
{
get => _name;
set => _name = value;
}
}
public class Car
{
private Person _owner;
private string _name;
public Person Owner
{
get => _owner;
set => _owner = value;
}
public string Name
{
get => _name;
set => _name = value;
}
}
If I set the AspectName of a column to Owner.Name it doesn't show anything on the list. I have made a small workaround of defining a property OwnerName inside the Car model, but I have more complex models which is a pain to have to define that property.
Is there a way I can do that?
Thanks
Based on what you have said then this should work. So there must be some other problem which is causing this issue.
You could try setting the AspectGetter programmatically instead such as this;
this.olvColumn2.AspectGetter = delegate (Object obj)
{
Car car = (Car)obj;
if (car == null)
return "Unknown";
else
return car.Owner.Name;
};
You can then put a breakpoint inside this code and see when/if it is called and what happens.
Remember that you must define/set all of the aspect getters etc. before you call objectListView1.SetObjects
Suppose in a C# WPF class I have something like this:
class test: INotifyPropertyChanged
{
private datetime _DOB
public datetime DOB
{
get
{
return _DOB;
}
set
{
if (_DOB != value)
{
_DOB = value;
RaisePropertyChanged();
}
}
}
private int _age
public int Age
{
get
{
return _age;
}
set
{
if (_age != value)
{
_age = value;
RaisePropertyChanged();
}
}
}
....
}
Now, let us suppose that a user can put in any of the properties. They can put in either their DOB, or their age, so making one of them calculated property would not work.
Apart from using methods like UpdateAge() in the setter of DOB and UpdateDOB() in the setter of Age, is there any other method that would automatically update the "dependent" properties along with the dependency properties (which INPC takes care of)?
is there any other method that would automatically update the "dependent" properties along with the dependency properties (which INPC takes care of)?
There is no "automatic" or magic here. You need to set the backing field and raise the PropertyChanged event for the data bound property that you want to refresh in the view.
Just make sure that you don't end up in an infinite loop where you set the Age property from the DOB property and vice versa.
You could set the _age backing field in the setter of the DOB property and vice versa, e.g.:
private DateTime _DOB;
public DateTime DOB
{
get
{
return _DOB;
}
set
{
if (_DOB != value)
{
_DOB = value;
RaisePropertyChanged();
_age = DateTime.Now.Year - _DOB.Year;
RaisePropertyChanged("Age");
}
}
}
Preamble: I am making a logging tool for our company needs. We use MVVM - pattern in our projects via Caliburn. At this moment my tool is capable of weaving compiled code via Mono.Cecil assembly and injecting call of a logging method in public properties set methods.
Fabula: Let's say, I have a class Person
public class Person
{
public string Name
{
get { return _name; }
set
{
Logger.MyLogMethod(_name, value, "Person");
_name = value;
}
}
private string _name;
}
and a class Logger
public static class Logger
{
public static void MyLogMethod(string oldvalue, string newvalue, string propertyname)
{
//condition to log only user changes
}
}
And an instance of a person has its Name property binded to textbox
<TextBox Text="{Binding SelectedPerson.Name}"/>
And we have a button, which click calls a code, which will set new value to SelectedPerson.
So, we have two ways of setting our Person's Name property at a runtime. It's either by user typing in textbox, or a user clicking a button, therefore calling some code.
I would like to know: how to distinct these two cases. In other words - when a set method of a property is called - how to determine, if it was called by binding engine or by our code.
So far I have one approach that is doable in my opinion - to take a look at StackTrace. Not sure how to do it thought.
You can make the Name property private. Then you expose a public property for binding and another for the rest of the application.
You can know differentiate a call from binding from a call from somewhere else
public class Person
{
string NameForOthers
{
get { return Name; }
set
{
Logger.MyLogMethod(_name, value, "Person name set by other place");
Name= value;
}
}
public string NameForBinding
{
get { return Name; }
set
{
Logger.MyLogMethod(_name, value, "Person name set by binding");
Name= value;
}
}
string Name
{
get { return _name; }
set
{
Logger.MyLogMethod(_name, value, "Person");
_name = value;
}
}
private string _name;
}
Then you use it for your binding
<TextBox Text="{Binding SelectedPerson.NameForBinding}"/>
I have a property defined with no explicit mention of backing field in a way like this :
//How to fire RaisePropertyChanged("Name") from setter
public string Name { get; set; }
How exactly do I fire a RaisePropertyChanged event in the setter of this property ?
I know how to do it when there is a private backing field and with a public property encapsulating it.
Is a multi line setter allowed in this scenario ?
No, you can't do this with an automatic property. You'll need to have a backing field and define both the getter and setter yourself, and raise the event in the setter as you described.
That's an Automatic Property, you need to have a backing field.
private string _name;
public string Name
{
get { return name; }
set
{
name = value;
RaisePropertyChanged("Name");
}
}
I have a custom Dependency Property defined like so:
public static readonly DependencyProperty MyDependencyProperty =
DependencyProperty.Register(
"MyCustomProperty", typeof(string), typeof(MyClass));
private string _myProperty;
public string MyCustomProperty
{
get { return (string)GetValue(MyDependencyProperty); }
set
{
SetValue(MyDependencyProperty, value);
}
}
Now I try set that property in XAML
<controls:TargetCatalogControl MyCustomProperty="Boo" />
But the setter in DependencyObject never gets hit! Although it does when I change the property to be a regular property and not a Dep Prop
Try this..
public string MyCustomProperty
{
get
{
return (string)GetValue(MyCustomPropertyProperty);
}
set
{
SetValue(MyCustomPropertyProperty, value);
}
}
// Using a DependencyProperty as the backing store for MyCustomProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyCustomPropertyProperty =
DependencyProperty.Register("MyCustomProperty", typeof(string), typeof(TargetCatalogControl), new UIPropertyMetadata(MyPropertyChangedHandler));
public static void MyPropertyChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// Get instance of current control from sender
// and property value from e.NewValue
// Set public property on TaregtCatalogControl, e.g.
((TargetCatalogControl)sender).LabelText = e.NewValue.ToString();
}
// Example public property of control
public string LabelText
{
get { return label1.Content.ToString(); }
set { label1.Content = value; }
}
It doesn't, unless you call it manually. There's a property-changed handler you can add to the DependancyProperty constructor call to be notified of when the property changes.
Call this constructor:
http://msdn.microsoft.com/en-us/library/ms597502.aspx
With a PropertyMetadata instance created by this constructor:
http://msdn.microsoft.com/en-us/library/ms557327.aspx
EDIT: Also, you are not implementing the dependancy property correctly. Your get and set should use GetValue and SetValue respectively, and you should not have a class member to store the value. The member name of the DP should also be {PropertyName}Property, e.g. MyCustomPropertyProperty if the get/set and property name as registered is MyCustomProperty. See http://msdn.microsoft.com/en-us/library/ms753358.aspx for more information.
Hope that helps.
Maybe you are using MVVM, and overriding the DataContext of your View ?
If you do, then the event for changing MyCustomProperty will be raised on the original DataContext and not on the new ViewModel.