Databinding setting to null and starting new - wpf

I have in my App class an object Order, both implementing INotfiyPropertyChanged.
When an Order is concluded, I set it to null and do a new Order() for restarting a new Order.
The problem is: it seems the objects that whose DataContext was bound to Order seems they are always linked to the older Order
What can I do to for not having to rebind again manually when I restart an Order?
For every object with this DataContext, I need to do object.DataContext= App.Order. What can I do to avoid this?
Some code:
public partial class App : Application, INotifyPropertyChanged
{
private Order m_order = new Order();
public Order Order
{
get { return m_order; }
set
{
m_order = value;
NotifyPropertyChanged("Order");
}
}
//...
public bool getOrderClosed()
{
if (Order != null)
{
Order = null;
}
return (Order == null);
}
public bool getOrderOpened()
{
if (Order == null)
Order = new Order();
return (Order != null);
}
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
//code on the part where the order is finished
private void Confirm_Click(object sender, RoutedEventArgs e)
{
//...
if (SaveOrder())
{
theApp.getOrderClosed();
theApp.getOrderOpened();
theApp.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.Basket.DataContext = theApp.Order;
}
}

If I understand correctly, your Order object is the DataContext. If you're setting the DataContext in codebehind, it'd looks something like:
[some_element].DataContext = myApp.Order;
What you'd need to do is bind the DataContext to myApp.Order. This way, when you do something like
myApp.Order = new Order(...);
the DataContext for [some_element] will change as well. If you post your XAML code where you're using the Order object as the DataContext, I can show you exactly what your binding on the DataContext should look like.
With what you've done, only the changes within the DataContext will be picked up; when you change the property that you're using as the DataContext changes, the DataContext itself does not.

I had a similar problem a few weeks ago. I found that when assigning a bound property to a new object the binding was lost, so as a workaround I had to create a new temp object and then copy all the fields into my bound property, that way you effectivly have a fresh object and the binding is maintained.
Hope this helps!

Maybe change the binding to UpdateSourceTrigger=PropertyChanged?

If App implements INotifyPropertyChanged properly, it will fire when you set App.Order to a new instance, and the binding will update.
Are you sure it is implemented properly?
eg.
class App
{
public Order Order
{
get
{
return _order;
}
set
{
if (value != _order)
{
_order = value;
FirePropertyChanged("Order");
}
}
}
}

Related

Call to NotifyProportyChanged when adding items to List doesn't work, why?

I'm trying to understand why calling the function (code below...) of NotifyProportyChanged from AddNoteToList to update the view whenever item added to list isn't working.
It works great when I'm doing an assignment on the list, but if I'm trying to add items and then call manually the NotifyProportyChanged it doesn't.
I know I should use ObservableCollection to solve the problem, but I would like to know why this implementation I wrote is not doing the job.
public class MainWindowVM : INotifyPropertyChanged
{
public Model.MainWindowModel Model { get; set; }
public List<DataProtocol.Note> _notesListVM;
public List<DataProtocol.Note> NotesListVM
{
get
{
return _notesListVM;
}
set
{
_notesListVM = value;
NotifyProportyChanged("NotesListVM");
}
}
//dp:
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyProportyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
//Command:
public RelayCommand AddNoteCommand { get; set; }
public void AddNoteToList(object parm)
{
string value = parm.ToString();
NotesListVM.Add(new DataProtocol.Note(value));
NotifyProportyChanged("NotesListVM");
}
public MainWindowVM()
{
Model = new PL.Model.MainWindowModel();
NotesListVM = Model.NotesList;
AddNoteCommand = new RelayCommand(AddNoteToList);
}
}
Even though you are raising PropertyChanged, the object instance NotesListVM hasn't actually changed, only its content has. WPF is optimized enough to realize this and do nothing.
If you really wanted to do it your way, you'd need create and assign a new list each time.
As you say, use ObservableCollection instead, which will fire CollectionChanged.
ItemsControl.ItemsSource is a dependency property, and will only register a change when you actually set the value to a different collection instance - sending a PropertyChanged event isn't sufficient.
As you noted, using an ObservableCollection is the correct way to have your bound U.I. controls detect that items have been added / removed from your list of items.

How to destroy or detach a CollectionView

I observe an odd behaviour of WPF ItemsControls: If a set the ItemsSource to an object which implements INotifyCollectionChanged and after that set the ItemsSource to null, the CollectionView which was created to provide the data to the ItemsControl still listens to the CollectionChanged-event of the source object.
If now the source collection is changed through a different thread, the CollectionView throws an exception (without being attached to any control).
While I understand why this is happening, I’m really stuck resolving this situation.
Therefore the main question is, how can I destroy a CollectionView so that it does not listen any more to CollectionChanged-event. Or how can I disable it doing that / detaching the underlying collection.
Please note: The described behavior is not with ObservableCollection. The source object is an IEnumerable of T and implements INotifyCollectionChanged.
You're looking for the CollectionView.DetachFromSourceCollection() method:
var collectionView = CollectionViewSource.GetDefaultView(yourEnumerable) as CollectionView;
collectionView.DetachFromSourceCollection();
Update
It seems, that under .net 4.5 there is this desired functionality. See the answer of HighCore. For those not having 4.5 I leave my workaround here, maybe it helps someone:
class DetachableNotifyCollectionChangedWrapper : IEnumerable, INotifyCollectionChanged {
IEnumerable m_source;
public event NotifyCollectionChangedEventHandler CollectionChanged;
public DetachableNotifyCollectionChangedWrapper(IEnumerable enumerable) {
if (null == enumerable) throw new ArgumentNullException("enumerable"); ;
m_source = enumerable;
var ncc = m_source as INotifyCollectionChanged;
if (null != ncc) ncc.CollectionChanged += SourceCollectionChanged;
}
void SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
if (null != CollectionChanged) CollectionChanged(this,e);
}
public IEnumerator GetEnumerator() {
return m_source.GetEnumerator();
}
public void Detach() {
var ncc = m_source as INotifyCollectionChanged;
if (null != ncc) ncc.CollectionChanged -= SourceCollectionChanged;
}
}
To use this, set the Wrapper as the ItemsSource of the ItemsControl. Before setting then the ItemsSource to null, call Detach on the wrapper to unregister the changed-event. Something as follows:
var wrapper = m_lstLog.ItemsSource as DetachableNotifyCollectionChangedWrapper;
if (null != wrapper) wrapper.Detach();
m_lstLog.ItemsSource = null;
The wrapper can also be used from within a ViewModel.

Dependecy properties that depend on other properties

Class C implements INotifyPropertyChanged.
Assume the C has Length, Width and Area propreties, where Area = Length * Width. A change in either might cause a change in area. All three are bound, i.e. the UI expects all three to notify of changes in their values.
When either Length or Width change, their setters call NotifyPropertyChanged.
How should I treat the calculated Area property? Currently the pattern I can think of is detecting in NotifyPropertyChanged whether the changed property is either Length or Width and, if such is the case, initiate an addional PropertyChanged notification for Area. This, however, requires that I maintain inside NotifyPropertyChanged the dependencies graph, which I feel is an anti-pattern.
So, my question is: How should I code dependency properties that depend on other dependency properties?
edit: People here suggested that Length and Width also call NotifyPropertyChanged for Area. Again, I think this is an anti-pattern. A property (IMHO) shouldn't be aware of who depends on it, as shouldn't NotifyPropertyChanged. Only the property should be aware of who it depends on.
This issue kept on bugging me, so I re-opened it.
First, I'd like to appologize for anyone taking my "anti-pattern" comment personally. The solutions offered here were, indeed, how-it's-done in WPF. However, still, IMHO they're bad practices caused, deficiencies in ther framework.
My claim is that the information hiding guide dictates that when B depeneds on A, A should not be aware of B. For exmaple, when B derives from A, A should not have code saying: "If my runtime type is really a B, then do this and that". Simiarily, when B uses A, A should not have code saying: "If the object calling this method is a B, then ..."
So it follows that if property B depends on property A, A shouldn't be the one who's responsible to alert B directly.
Conversely, maintaining (as I currently do) the dependencies graph inside NotifyPropertyChanged is also an anti-pattern. That method should be lightweight and do what it name states, not maintain dependency relationships between properties.
So, I think the solution needed is through aspect oriented programming: Peroperty B should use an "I-depend-on(Property A)" attribute, and some code-rewriter should create the dependency graph and modify NotifyPropertyChanged transparently.
Today, I'm a single programmer working on a single product, so I can't justify dvelving with this any more, but this, I feel, is the correct solution.
Here is an article describing how to create a custom attribute that automatically calls PropertyChanged for properties depending on another property: http://www.redmountainsw.com/wordpress/2012/01/17/a-nicer-way-to-handle-dependent-values-on-propertychanged/
The code will look like this:
[DependsOn("A")]
[DependsOn("B")]
public int Total
{
get { return A + B; }
}
public int A
{
get { return m_A; }
set { m_A = value; RaisePropertyChanged("A"); }
}
public int B
{
get { return m_B: }
set { m_B = value; RaisePropertyChanged("B"); }
}
I haven't tried it myself but I like the idea
When the Length or Width properties are changed you fire PropertyChanged for Area in addition to firing it for either Length or Width.
Here is a very simple implementation based on backing fields and the method OnPropertyChanged to fire the PropertyChanged event:
public Double Length {
get { return this.length; }
set {
this.length = value;
OnPropertyChanged("Length");
OnPropertyChanged("Area");
}
}
public Double Width {
get { return this.width; }
set {
this.width = value;
OnPropertyChanged("Width");
OnPropertyChanged("Area");
}
}
public Double Area {
get { return this.length*this.width; }
}
Doing it like this is certainly not an anti-pattern. That is exactly the pattern for doing it. You as the implementer of the class knows that when Length is changed then Area is also changed and you encode it by raising the appropriate event.
Then you should raise twice, in Length and Width property setters. One for the actual property and one for the Area property.
for example:
private int _width;
public int Width
{
get { return _width; }
set
{
if (_width == value) return;
_width = value;
NotifyPropertyChanged("Width");
NotifyPropertyChanged("Area");
}
}
People here suggested that Length and Width also call
NotifyPropertyChanged for Area. Again, I think this is an
anti-pattern. A property (IMHO) shouldn't be aware of who depends on
it, as shouldn't NotifyPropertyChanged. Only the property should be
aware of who it depends on.
This is not an anti-pattern. Actually, your data encapsulated inside this class, so this class knows when and what changed. You shouldn't know outside of this class that Area depends on Width and Length. So the most logical place to notify listeners about Area is the Width and Length setter.
A property (IMHO) shouldn't be aware of who depends on it, as
shouldn't NotifyPropertyChanged.
It does not break encapsulation, because you are in the same class, in the same data structure.
An extra information is that knockout.js (a javascript mvvm library) has a concept which accessing this problem: Computed Observables. So I believe this is absolutely acceptable.
Here is a possible implementation of an attribute:
public class DependentPropertiesAttribute : Attribute
{
private readonly string[] properties;
public DependentPropertiesAttribute(params string[] dp)
{
properties = dp;
}
public string[] Properties
{
get
{
return properties;
}
}
}
Then in the Base View Model, we handle the mechanism of calling property dependencies:
public class ViewModelBase : INotifyPropertyChanged
{
public ViewModelBase()
{
DetectPropertiesDependencies();
}
private readonly Dictionary<string, List<string>> _dependencies = new Dictionary<string, List<string>>();
private void DetectPropertiesDependencies()
{
var propertyInfoWithDependencies = GetType().GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(DependentPropertiesAttribute))).ToArray();
foreach (PropertyInfo propertyInfo in propertyInfoWithDependencies)
{
var ca = propertyInfo.GetCustomAttributes(false).OfType<DependentPropertiesAttribute>().Single();
if (ca.Properties != null)
{
foreach (string prop in ca.Properties)
{
if (!_dependencies.ContainsKey(prop))
{
_dependencies.Add(prop, new List<string>());
}
_dependencies[prop].Add(propertyInfo.Name);
}
}
}
}
protected void OnPropertyChanged(params Expression<Func<object>>[] expressions)
{
expressions.Select(expr => ReflectionHelper.GetPropertyName(expr)).ToList().ForEach(p => {
RaisePropertyChanged(p);
RaiseDependentProperties(p, new List<string>() { p });
});
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected virtual void RaisePropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected void RaiseDependentProperties(string propertyName, List<string> calledProperties = null)
{
if (!_dependencies.Any() || !_dependencies.ContainsKey(propertyName))
return;
if (calledProperties == null)
calledProperties = new List<string>();
List<string> dependentProperties = _dependencies[propertyName];
foreach (var dependentProperty in dependentProperties)
{
if (!calledProperties.Contains(dependentProperty))
{
RaisePropertyChanged(dependentProperty);
RaiseDependentProperties(dependentProperty, calledProperties);
}
}
}
}
Finally we define dependencies in our ViewModel
[DependentProperties("Prop1", "Prop2")]
public bool SomeCalculatedProperty
{
get
{
return Prop1 + Prop2;
}
}

Implementing NotifyPropertyChanged without magic strings [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
typesafe NotifyPropertyChanged using linq expressions
I'm working on a large team application which is suffering from heavy use of magic strings in the form of NotifyPropertyChanged("PropertyName"), - the standard implementation when consulting Microsoft. We're also suffering from a great number of misnamed properties (working with an object model for a computation module that has hundreds of stored calculated properties) - all of which are bound to the UI.
My team experiences many bugs related to property name changes leading to incorrect magic strings and breaking bindings. I wish to solve the problem by implementing property changed notifications without using magic strings. The only solutions I've found for .Net 3.5 involve lambda expressions. (for example: Implementing INotifyPropertyChanged - does a better way exist?)
My manager is extremely worried about the performance cost of switching from
set { ... OnPropertyChanged("PropertyName"); }
to
set { ... OnPropertyChanged(() => PropertyName); }
where the name is extracted from
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression)
{
MemberExpression body = selectorExpression.Body as MemberExpression;
if (body == null) throw new ArgumentException("The body must be a member expression");
OnPropertyChanged(body.Member.Name);
}
Consider an application like a spreadsheet where when a parameter changes, approximately a hundred values are recalculated and updated on the UI in real-time. Is making this change so expensive that it will impact the responsiveness of the UI? I can't even justify testing this change right now because it would take about 2 days worth of updating property setters in various projects and classes.
I did a thorough test of NotifyPropertyChanged to establish the impact of switching to the lambda expressions.
Here were my test results:
As you can see, using the lambda expression is roughly 5 times slower than the plain hard-coded string property change implementation, but users shouldn't fret, because even then it's capable of pumping out a hundred thousand property changes per second on my not so special work computer. As such, the benefit gained from no longer having to hard-code strings and being able to have one-line setters that take care of all your business far outweighs the performance cost to me.
Test 1 used the standard setter implementation, with a check to see that the property had actually changed:
public UInt64 TestValue1
{
get { return testValue1; }
set
{
if (value != testValue1)
{
testValue1 = value;
InvokePropertyChanged("TestValue1");
}
}
}
Test 2 was very similar, with the addition of a feature allowing the event to track the old value and the new value. Because this features was going to be implicit in my new base setter method, I wanted to see how much of the new overhead was due to that feature:
public UInt64 TestValue2
{
get { return testValue2; }
set
{
if (value != testValue2)
{
UInt64 temp = testValue2;
testValue2 = value;
InvokePropertyChanged("TestValue2", temp, testValue2);
}
}
}
Test 3 was where the rubber met the road, and I get to show off this new beautiful syntax for performing all observable property actions in one line:
public UInt64 TestValue3
{
get { return testValue3; }
set { SetNotifyingProperty(() => TestValue3, ref testValue3, value); }
}
Implementation
In my BindingObjectBase class, which all ViewModels end up inheriting, lies the implementation driving the new feature. I've stripped out the error handling so the meat of the function is clear:
protected void SetNotifyingProperty<T>(Expression<Func<T>> expression, ref T field, T value)
{
if (field == null || !field.Equals(value))
{
T oldValue = field;
field = value;
OnPropertyChanged(this, new PropertyChangedExtendedEventArgs<T>(GetPropertyName(expression), oldValue, value));
}
}
protected string GetPropertyName<T>(Expression<Func<T>> expression)
{
MemberExpression memberExpression = (MemberExpression)expression.Body;
return memberExpression.Member.Name;
}
All three methods meet at the OnPropertyChanged routine, which is still the standard:
public virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(sender, e);
}
Bonus
If anyone's curious, the PropertyChangedExtendedEventArgs is something I just came up with to extend the standard PropertyChangedEventArgs, so an instance of the extension can always be in place of the base. It leverages knowledge of the old value when a property is changed using SetNotifyingProperty, and makes this information available to the handler.
public class PropertyChangedExtendedEventArgs<T> : PropertyChangedEventArgs
{
public virtual T OldValue { get; private set; }
public virtual T NewValue { get; private set; }
public PropertyChangedExtendedEventArgs(string propertyName, T oldValue, T newValue)
: base(propertyName)
{
OldValue = oldValue;
NewValue = newValue;
}
}
Personally I like to use Microsoft PRISM's NotificationObject for this reason, and I would guess that their code is reasonably optimized since it's created by Microsoft.
It allows me to use code such as RaisePropertyChanged(() => this.Value);, in addition to keeping the "Magic Strings" so you don't break any existing code.
If I look at their code with Reflector, their implementation can be recreated with the code below
public class ViewModelBase : INotifyPropertyChanged
{
// Fields
private PropertyChangedEventHandler propertyChanged;
// Events
public event PropertyChangedEventHandler PropertyChanged
{
add
{
PropertyChangedEventHandler handler2;
PropertyChangedEventHandler propertyChanged = this.propertyChanged;
do
{
handler2 = propertyChanged;
PropertyChangedEventHandler handler3 = (PropertyChangedEventHandler)Delegate.Combine(handler2, value);
propertyChanged = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref this.propertyChanged, handler3, handler2);
}
while (propertyChanged != handler2);
}
remove
{
PropertyChangedEventHandler handler2;
PropertyChangedEventHandler propertyChanged = this.propertyChanged;
do
{
handler2 = propertyChanged;
PropertyChangedEventHandler handler3 = (PropertyChangedEventHandler)Delegate.Remove(handler2, value);
propertyChanged = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref this.propertyChanged, handler3, handler2);
}
while (propertyChanged != handler2);
}
}
protected void RaisePropertyChanged(params string[] propertyNames)
{
if (propertyNames == null)
{
throw new ArgumentNullException("propertyNames");
}
foreach (string str in propertyNames)
{
this.RaisePropertyChanged(str);
}
}
protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
string propertyName = PropertySupport.ExtractPropertyName<T>(propertyExpression);
this.RaisePropertyChanged(propertyName);
}
protected virtual void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler propertyChanged = this.propertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public static class PropertySupport
{
// Methods
public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
{
if (propertyExpression == null)
{
throw new ArgumentNullException("propertyExpression");
}
MemberExpression body = propertyExpression.Body as MemberExpression;
if (body == null)
{
throw new ArgumentException("propertyExpression");
}
PropertyInfo member = body.Member as PropertyInfo;
if (member == null)
{
throw new ArgumentException("propertyExpression");
}
if (member.GetGetMethod(true).IsStatic)
{
throw new ArgumentException("propertyExpression");
}
return body.Member.Name;
}
}
If you're concerned that the lambda-expression-tree solution might be too slow, then profile it and find out. I suspect the time spent cracking open the expression tree would be quite a bit smaller than the amount of time the UI will spend refreshing in response.
If you find that it is too slow, and you need to use literal strings to meet your performance criteria, then here's one approach I've seen:
Create a base class that implements INotifyPropertyChanged, and give it a RaisePropertyChanged method. That method checks whether the event is null, creates the PropertyChangedEventArgs, and fires the event -- all the usual stuff.
But the method also contains some extra diagnostics -- it does some Reflection to make sure that the class really does have a property with that name. If the property doesn't exist, it throws an exception. If the property does exist, then it memoizes that result (e.g. by adding the property name to a static HashSet<string>), so it doesn't have to do the Reflection check again.
And there you go: your automated tests will start failing as soon as you rename a property but fail to update the magic string. (I'm assuming you have automated tests for your ViewModels, since that's the main reason to use MVVM.)
If you don't want to fail quite as noisily in production, you could put the extra diagnostic code inside #if DEBUG.
Actually we discussed this aswell for our projects and talked alot about the pros and cons. In the end, we decided to keep the regular method but used a field for it.
public class MyModel
{
public const string ValueProperty = "Value";
public int Value
{
get{return mValue;}
set{mValue = value; RaisePropertyChanged(ValueProperty);
}
}
This helps when refactoring, keeps our performance and is especially helpful when we use PropertyChangedEventManager, where we would need the hardcoded strings again.
public bool ReceiveWeakEvent(Type managerType, object sender, System.EventArgs e)
{
if(managerType == typeof(PropertyChangedEventManager))
{
var args = e as PropertyChangedEventArgs;
if(sender == model)
{
if (args.PropertyName == MyModel.ValueProperty)
{
}
return true;
}
}
}
One simple solution is to simply pre-process all files before compilation, detect the OnPropertyChanged calls that are defined in set { ... } blocks, determine the property name and fix the name parameter accordingly.
You could do this using an ad-hoc tool (that would be my recommendation), or use a real C# (or VB.NET) parser (like those which can be found here: Parser for C#).
I think it's reasonable way to do it. Of course, it's not very elegant nor smart, but it has zero runtime impact, and follows Microsoft rules.
If you want to save some compile time, you could have both ways using compilation directives, like this:
set
{
#if DEBUG // smart and fast compile way
OnPropertyChanged(() => PropertyName);
#else // dumb but efficient way
OnPropertyChanged("MyProp"); // this will be fixed by buid process
#endif
}

How to use PropertyChanged to pass trough DataTemplate?

Question is simple: how can I trigger a change on the dataObject without acutaly changing the dataObject, and see this change on the visual?
DataObject:
ProductData : INotifyPropertyChanged
{
private ProductPartData myProductPartData;
public ProductPartData ProductPartData
{
get
{
return myProductPartData;
}
set
{
if (value != myProductPartData)
{
myProductPartData = value;
OnNotifyPropertyChanged("ProductPartData");
}
}
}
}
DataTemplate:
<DataTemplate
DataType="{x:Type ProductData}"
>
<VisualProduct
ProductPartData="{Binding Path=ProductPartData, Mode=OneWay}"
/>
</DataTemplate>
And now in a VM I have:
product.OnNotifyPropertyChanged("ProductPartData");
Problem:
Even if the getter for ProductPart is called when I execute OnNotifyPropertyChanged, the visual is not notified, because is the same instance of the ProductPartData.
How do I trigger a change seen by the Visual without changing the instance?
Thank you,
Daniel,
A solution is to use UpdateTarget() method of the BindingExpression class, this way the target of the binding gets refreshed no matter what; of course, your converter will also be hit - if any. Since I'm guessing you don't have access to your visual in the Product, you could use an attached property and in its callback, you can get the BindingExpression and call UpdateTarget() on it.
Note that I'm using a simple TextBlock as the visual of the data object.
public class BindingHelper
{
public static bool GetRefreshBinding(DependencyObject obj)
{
return (bool) obj.GetValue(RefreshBindingProperty);
}
public static void SetRefreshBinding(DependencyObject obj, bool value)
{
obj.SetValue(RefreshBindingProperty, value);
}
// Using a DependencyProperty as the backing store for RefreshBinding. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RefreshBindingProperty =
DependencyProperty.RegisterAttached("RefreshBinding", typeof(bool), typeof(BindingHelper), new UIPropertyMetadata(false, OnRefreshBindingPropertyChanged));
static void OnRefreshBindingPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs ea)
{
TextBlock elem = o as TextBlock;
if (elem != null)
{
BindingExpression bEx = elem.GetBindingExpression(TextBlock.TextProperty);
if (bEx != null)
{
bEx.UpdateTarget();
}
}
}
}
Also, in your data object that you can create a new bool property(let's name it ShouldRefresh) that is bound to the attached property within the template - this will trigger the AP's property changing:
<DataTemplate DataType="{x:Type local:ProductData}">
<TextBlock Text="{Binding Path=Name, Converter={StaticResource BlankConverter}}"
local:BindingHelper.RefreshBinding="{Binding Path=ShouldRefresh}"/>
</DataTemplate>
So, this way, whenever you want to update the target through binding, you can set:
ShouldRefresh = !ShouldRefresh
in your data class.
HTH.
If you raise a PropertyChanged event and the new value of the property is equal to the value WPF already has, it will simply ignore you. You have a couple of options:
The "fast" way is to set the property to null and then back to the correct value again, ensuring PropertyChanged events are raised each time. It's dirty but it works every time.
The "right" way is to force a binding refresh as discussed in this post by Jaime Rodriguez. Because your visual is data-templated though getting the "dependencyObject" to pass into the call in that post is a little tricky. You may end up needing to use the template's FindName method as discussed in this post by Josh Smith.
We encountered this kind of issue with data coming from a database and converted to a DTO (data transfert object).
Our base class for DTO override Object's method such as Equals() and GetHashCode() as follow:
public override Boolean Equals(Object obj)
{
// Null reference
if (null == obj)
return false;
// Same reference
if (Object.ReferenceEquals(this, obj))
return true;
EntityDTOBase<TEntity> entiteObj = obj as EntityDTOBase<TEntity>;
if (null == entiteObj)
return false;
else
return Equals(entiteObj);
}
public Boolean Equals(EntityDTOBase<TEntity> other)
{
// Null reference
if (null == other)
return false;
// Same reference
if (Object.ReferenceEquals(this, other))
return true;
// No Id: cannot be compared, return false
if (this.id == TypeHelper.DefaultValue<long>())
return false;
// Id comparison
if (this.id != other.id)
return false;
return true;
}
public override Int32 GetHashCode()
{
return this.id.GetHashCode();
}
So the problem was when we load again the same entity from the database, since the ID is the same, some binding were not properly updated.
This particular issue was circumvented by adding an additional virtual EqualsExtended() method which default implementation simply returns true:
protected virtual Boolean EqualsExtended(EntityDTOBase<TEntity> other)
{
return true;
}
public Boolean Equals(EntityDTOBase<TEntity> other)
{
/// Same code as before (except last line):
return EqualsExtended(other);
}
Now in any implementation of our DTO class we can add some logic to make Equals() returning false in some situations, for example by adding a timestamp when data is retrieved from the database :
protected override Boolean EqualsExtended(EntityDTOBase<Act> other
{
if (this.Timestamp != other.Timestamp)
{
return false;
}
return true;
}
Long story short, one way to workaround this issue is to make your class instance look different whenever you want the GUI to update accordingly.
The problem might be that you are returning GuiProductPartData typed myProductPartData with ProductPartData typed ProductPartData? But in any case this shouldn't be like this :)
Also it's not a great practice to have the variable name same as the type, so you shouldn't have a ProductPartData ProductPartData property.
Naming conventions aside (and assuming just typos on the typing) the problem probably resides inside your ProductPartData class. Does it implement INotifyPropertyChanged as well?

Resources