Showing posts with label wpf. Show all posts
Showing posts with label wpf. Show all posts

Friday, August 1, 2008

WPF Data Binding Not Refreshing When Bound to Static Object

And the WPF Data Binding wierdness/frustration continues ...

I have a DataTemplate where DataType is defined. (In other words, WPF magic figures out when to use the template based on the type that is being bound). The Template includes a ComboBox which is bound to a static object in my UserControl class. The SelectedItem of the combobox is bound to a property of the DataTemplate's type (which, in this case, is a linq entity object).

It looks something like this:



My problem was that when I changed the DataContext of the UserControl which in turn changed the DataContext of this DataTemplate's parent control and the DataTemplate itself, the data in the ComboBox didn't change. In other words, while all the controls around it were being re-bound, this particular control wasn't.

Grrr.

After much googling, I found a cheap - but helpful - solution. Force the ComboBox to rebind every single time but adding a IValueConverter (which does nothing but return the value) to the binding.

Here is the article with the solution.

Seriously, these WPF Data Binding issues are ridiculous. I mean what exactly was Microsoft testing this shite for? It surely wasn't real-world examples or even with it's own new technology (Linq to SQL for example).

Tuesday, May 27, 2008

Random Annoying Crap about WPF Data Binding & Linq to SQL

For a new project at work, we are using WPF and Linq to Sql. In some ways data binding in WPF is very sexy and suave. In other ways, it's aggravating - there are things that are so easily done in WinForms and ASP .Net, like, say, re-binding data to a control after it's changed, that are bitch to figure out in WPF. At least for me they are.

In theory, WPF can update itself whenever the source changes. In reality, it's not quite as simple as it sounds.

First of all, if you happen to be extending the generic ObservableCollection and have a method in your new class that adds items to the collection, using the Add() method will update the control while using Items.Add() will not update the control. Why? Who knows?

public class ObservableStringCollection : ObservableCollection
{
public ObservableStringCollection()
{
Add("First");
Add("Middle");
Add("Last");

}

public void AddMe(string s)
{
Add(s); //I notify controls I'm bound to!
Items.Add(s); //I don't notify!
}
}


Secondly, Linq to Sql is not observable so anytime you SubmitChanges(), any control bound to your Linq classes doesn't get updated. I got around this by re-setting the ItemsSource property. Ok, fine. Here's the strange part: using ToArray() on the Linq collection will set the source correctly, while using AsEnumerable() will not set the source correctly. AsEnumerable() will set the source correctly the first time it's bound.


tvPages.ItemsSource = CMSUtility.DataContext.CMS_Pages.ToArray(); // I work!
tvPages.ItemsSource = CMSUtility.DataContext.CMS_Pages.AsEnumerable(); // I only work the first time!


Currently, I'm working on extending the Linq DataContext to be somewhat observable.

I wrapped the Linq DataContext class and implemented the INotifyPropertyChanged interface. Then I overrode the SubmitChanges method to fire the notification event.

public class ObservableDataContext : LinqClassesDataContext, INotifyPropertyChanged
{
public ObservableDataContext() : base("Data Source=.;Initial Catalog=DB;Integrated Security=True") { }

public ObservableDataContext(LinqClassesDataContext dc) : base(dc.Connection, dc.Mapping.MappingSource) { }

public override void SubmitChanges(System.Data.Linq.ConflictMode failureMode)
{
base.SubmitChanges(failureMode);
NotifyPropertyChanged("Nodes");

}

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

public void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}

#endregion
}
}

This way I can attach an event to the PropertyChanged for classes that I bind with.

That's the theory anyway. In practice, it's *sort of* working - I am able to get the Linq SubmitChanges to notify my source object and rebind to my control. However, when it binds to the control again, it doesn't use my DataTemplates. That's for another post I guess.

I'm off to yoga ...