I have a ListView bound to a LINQ to SQL object. When I double click an article in the ListView it opens the article details window and allow the user to change article properties.
So far, it all works fine, but when the user saves and closes the article det开发者_如何学运维ails, the ListView doesn't reflect the changes made (like the article's description for example). I don't want to implement INotifyPropertyChanged in all my LINQ classes because I use VS2010 to generate my Linq table schema, so it would be a pain to alter auto generated designer code... (and it will certainly override all my changes each time I will make a change to the table's schema)
How can I simply force the ListView to refresh the LINQ binding when the details window is closed?
Thank in advance for your help.
All Linq classes are generated as partial classes - this means you can create your own partial class that matches the Linq class and add any extra functionality required there. Then when it is compiled, it will all work as one class.
A quick and easy solution is to use a DynamicObject decorator to add the change notificcation behaviour without having to change your original classes, or writing a suite of partial class definitions
public class DynamicBindingProxy<T> : DynamicObject, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private static readonly Dictionary<string, Dictionary<string,
PropertyInfo>> properties = new Dictionary<string,
Dictionary<string, PropertyInfo>>();
private readonly T instance;
private readonly string typeName;
public DynamicBindingProxy(T instance)
{
this.instance = instance;
var type = typeof(T);
typeName = type.FullName;
if (!properties.ContainsKey(typeName))
SetProperties(type, typeName);
}
private static void SetProperties(Type type, string typeName)
{
var props = type.GetProperties(
BindingFlags.Public | BindingFlags.Instance);
var dict = props.ToDictionary(prop => prop.Name);
properties.Add(typeName, dict);
}
public override bool TryGetMember(GetMemberBinder binder,
out object result)
{
if (properties[typeName].ContainsKey(binder.Name))
{
result = properties[typeName][binder.Name]
.GetValue(instance, null);
return true;
}
result = null;
return false;
}
public override bool TrySetMember(SetMemberBinder binder,
object value)
{
if (properties[typeName].ContainsKey(binder.Name))
{
properties[typeName][binder.Name]
.SetValue(instance, value, null);
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(binder.Name));
return true;
}
return false;
}
}
and heres a sample useage:
public partial class MainWindow : Window
{
private readonly TestObj tObj;
private DynamicBindingProxy<TestObj> dynObj;
public MainWindow()
{
InitializeComponent();
tObj = new TestObj() { Name = "test", Amount = 123.45, ID = 44, SomeDate = DateTime.Now };
dynObj = new DynamicBindingProxy<TestObj>(tObj);
DataContext = dynObj;
}
private void UpdateName(object sender, RoutedEventArgs e)
{
((dynamic)dynObj).Name = newText.Text;
}
}
full details can be found on a blog post I wrote specifically about this issues http://www.deanchalk.me.uk/post/WPF-e28093-Easy-INotifyPropertyChanged-Via-DynamicObject-Proxy.aspx
精彩评论