Notify property changed in WCF service - wpf

I have a WPF application which calls WCF service methods through a Client which exposes these methods. Is there any way to bind my application to a property of the service, and to get notified when this property changes? I know INotifyPropertyChanged but I have some doubts about its efficiency in this case... Thanks
EDIT : Actually, all I want is my application to be notified of the changes that happen on the server side.

There are a couple of questsions here. You can bind your code to the client end of a WCF service and by using a partial class definition you can add an INotifyPropertyChanged interface to it so that it meets your design. But actually wiring up the mechanism for pushing updates from the server would be much harder.
In fact, Events will work over WCF, and reasonably performant i.e. you won't have the delay associated with polling. However I wouldn't try to squeeze your WCF code into fitting the INotifyPropertyChanged pattern. Instead use a more bespoke interface for the client/server comms and then expose the INotifyPropertyChanged back in the ViewModel.

Just add a delegate to your service, then call the service from your view model or code behind and reflect the changes with your properties that implement the INotifyPropertyChanged interface:
In Service:
public delegate void ServcieUpdate(SomeDataType data);
public ServcieUpdate OnServcieUpdated { get; set; }
When data is updated:
if (OnServcieUpdated != null) OnServcieUpdated(data);
In view model:
private ServiceClient serviceClient = new ServiceClient();
private ObservableCollection<SomeDataType> data = new
ObservableCollection<SomeDataType>();
public YourViewModel()
{
serviceClient.OnServiceUpdated += OnServcieUpdated;
}
public ObservableCollection<SomeDataType> Data
{
get { return data; }
set { data = value; NotifyPropertyChanged("Data");
}
public void OnServcieUpdated(SomeDataType data)
{
Data = data;
}
Please take a look at the Delegates (C# Programming Guide) page on MSDN in you are unfamiliar with using delegate objects.

Related

MVVM Light for Xamarin Forms and WPF

I'm trying to make an cross-plattform app, that will work for Xamarin.Forms and WPF (like this: https://github.com/C0D3Name/XamFormsWpf) in combination with MVVM light.
MVVM Light is quite new to me and i didn't find a clear tutorial for what i want to do. On Xamarin.Forms the DependencyInjection is done by
SQLiteConnection database = DependencyService.Get<ISQLite>().GetConnection("db.sqlite");
How is this done in MVVM light? Do i have to pass the different plattform-implementations of ISQLite in as parameter?
I already created the ViewModelLocator in my PCL:
public class ViewModelLocator
{
/// <summary>
/// Register all the used ViewModels, Services et. al. witht the IoC Container
/// </summary>
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<MainViewModel>();
// My DataService is using the connection from ISQlite
SimpleIoc.Default.Register<IDataService, DataService>();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
}
public interface ISQLite
{
SQLiteConnection GetConnection(string sqliteFilename);
}
As far as i understood the SimpleIoc, i have to register the interface to a concrete implementation, but how does my DataService know about the correct ISQLite Implementation?
I hope my question is understandable.
From official docs:
SimpleIoc - A very simple IOC container with basic functionality needed to register and resolve instances.
DependencyService - Xamarin.Forms allows developers to define behavior in platform-specific projects. DependencyService then finds the right platform implementation, allowing shared code to access the native functionality.
So you would want to use SimpleIoc to create your PCL dependency injection graph (IDataService for example)
And you will have to use DependencyService to provide platform specific functionality. One example for DependencyService use would be loading a html file located on the device into webview. Since the locations of assets on iOS and Android are different you will have add platform specific implementation for base url and then use DependencyService in your pcl. Another example would be IO.
So in your case if you need platform specific implementations of ISQlite you will have to use DependencyService. If not you may want (or not) to use SimpleIoc to add concrete implementation of ISQlite interface to your dependency graph.
Hope that helps.
Also have a look at Akavache. We use it with a great success in Xamarin.Forms projects.
Finally i found a working solution. The (async) Sqlite-Connection is used as parameter for my ViewModelLocator
public class App : Application
{
private static ViewModelLocator locator;
public static ViewModelLocator Locator
{
get
{
if (locator == null)
{
var connection = DependencyService.Get<ISQLite>().GetConnection("db.sqlite");
locator = new ViewModelLocator(connection);
}
return locator;
}
}
}
...and the locator injects the connection into the DataService constructor:
public class ViewModelLocator
{
public ViewModelLocator(SQLiteConnectionWithLock connection)
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<IDataService>(() => new DataService(connection));
// ViewModels
SimpleIoc.Default.Register<MainViewModel>();
}
public MainViewModel Main => ServiceLocator.Current.GetInstance<MainViewModel>();
}

Optional Dependency at Composition Root

I've written a WPF app that has two different main windows. I don't know which one to launch until runtime by looking up what kind of user is using the program in a database. The code I currently have works but Castle Windsor is doing tons of extra work by newing up the object graphs for both kinds of windows.
private readonly IMainWindow _mainWindow;
private readonly ISimplifiedMainWindow _simplifiedMainWindow;
public MainClass(
IMainWindow mainWindow,
ISimplifiedMainWindow simplifiedMainWindow)
{
_mainWindow = mainWindow;
_simplifiedMainWindow = simplifiedMainWindow;
}
public RunApp()
{ // pseudocode
if (user is fullUser) _mainWindow.Show();
else _simplifiedMainWindow.Show();
}
How do I defer creation of my window objects without resorting to making an abstract factory that will basically duplicate what Castle Windsor does anyway?
A factory is in fact the solution I'd recommend (and a solution I've successfully used multiple times in the past to solve this very problem).
I wouldn't implement the factory myself though, let Windsor do it (via a Typed Factory).
public interface IWindowFactory
{
IMainWindow FullUserWindow();
ISimplifiedMainWindow SimplifiedUserWindow();
//optionally
void DestroyWindow(IWindow window);
}
Now you just need to tell Windsor to build a factory for that interface
container.AddFacility<TypedFactoryFacility>();
// later on, in your installer
container.Register(Component.For<IWindowFactory>()
.AsFactory()
.LifestyleTransient());
and your app code changes to:
public RunApp()
{ // pseudocode
if (user is fullUser) Show(factory.FullUserWindow());
else Show(factory.SimplifiedUserWindow());
}

Issue intercepting property in Silverlight application

I am using Ninject as DI container in a Silverlight application. Now I am extending the application to support interception and started integrating DynamicProxy2 extension for Ninject. I am trying to intercept call to properties on a ViewModel and ending up getting following exception:
“Attempt to access the method failed: System.Reflection.Emit.DynamicMethod..ctor(System.String, System.Type, System.Type[], System.Reflection.Module, Boolean)”
This exception is thrown when invocation.Proceed() method is called. I tried two implementations of the interceptor and they both fail
public class NotifyPropertyChangedInterceptor: SimpleInterceptor
{
protected override void AfterInvoke(IInvocation invocation)
{
var model = (IAutoNotifyPropertyChanged)invocation.Request.Proxy;
model.OnPropertyChanged(invocation.Request.Method.Name.Substring("set_".Length));
}
}
public class NotifyPropertyChangedInterceptor: IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
var model = (IAutoNotifyPropertyChanged)invocation.Request.Proxy;
model.OnPropertyChanged(invocation.Request.Method.Name.Substring("set_".Length));
}
}
I want to call OnPropertyChanged method on the ViewModel when property value is set.
I am using Attribute based interception.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class NotifyPropertyChangedAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
if(request.Method.Name.StartsWith("set_"))
return request.Context.Kernel.Get<NotifyPropertyChangedInterceptor>();
return null;
}
}
I tested the implementation with a Console Application and it works alright.
I also noted in Console Application as long as I had Ninject.Extensions.Interception.DynamicProxy2.dll in same folder as Ninject.dll I did not have to explicitly load DynamicProxy2Module into the Kernel, where as I had to explicitly load it for Silverlight application as follows:
IKernel kernel = new StandardKernel(new DIModules(), new DynamicProxy2Module());
Could someone please help? Thanks
Reflection can be really tricky in silverlight because of security issues.
Check Gabe's answer for this question, it's the same problem.
The good news is that you can achieve the same functionality you want using dynamic instead of proxies. Just extend your ViewModel from DynamicObject and override the TrySetMember method.
I hope it helps :)

ADO.NET DataServices with Prism

I've start using prism with silverlight 3, but, we are trying to implement it to work with ADO.NET DataServices. The "DataServiceQuery" query type required to use with Silverlight, requires a Asyncronous call to be fired after the query. This will break ous Prism Pattern by what I can see.
Any ideas to get only the data of the query to use in Prism Pattern? Correct-me anyone if i'm wrong!
Making an Asynchronous call to your server doesn't break "Prism Pattern". When your view needs to query the server, its viewmodel fires an asynchronous request and provides a callback. Once callback is called, it handles the result and updates whatever properties it exposes to a view. This will result in view updating according to bindings you set up in your xaml.
PL is exactly right. There's really no patterns that Prism encourages that are incompatible with ADO.NET Data Services. There are just a few things you should know.
Here's a small sample. It's a little tricky... the complete event will sometimes fire outside of the UI thread, so you have to handle it with the dispatcher (at least in SL2 you did):
public class MyViewModel : BaseViewModel
{
public Customer CustomerResult
{
...
}
NorthwindEntities svcContext = null;
public MyViewModel()
{
svcContext =
new NorthwindEntities(new Uri("Northwind.svc", UriKind.Relative));
DataServiceQuery<Customers> query =
svcContext.Customers.Expand("Orders");
// Begin the query execution.
query.BeginExecute(WorkComplete, query);
}
private void WorkComplete(IAsyncResult result)
{
DataServiceQuery<Customers> query =
result.AsyncState as DataServiceQuery<Customers>;
Customers returnedCustomer =
query.EndExecute(result).FirstOrDefault();
//Execute with the dispatcher
Dispatcher.CurrentDispatcher.BeginInvoke( () =>
{
CustomerResult = returnedCustomer;
});
}
}
Of course there is no exception handling in here, but you get the picture hopefully.

DeSerialized attribute in Silverlight

I have reasonably limited data to move between silverlight and a WCF service. So I have set up some datacontracts. I was hoping to be able to use the same classes to use for some limited data validation on the client side, without needing the overhead of DTOs and stuff.
I have a contract something like this:
[DataContract]
class MyObject
{
private String _id;
[DataMember]
public String ID
{
get
{
return _id;
}
set
{
_id = value;
DoStuff();
}
}
Now when I deserialize the object the setter will be run. This will set the private variable _id which is good. But I don't want the DoStuff() to be run on deserialization.
I had hoped to use the [OnDeserializing] and [OnDeserialized] attributes. I could have defined a bool flag that I could use to control what gets run in the setter. This actually works on the server side but Silverlight doesn't have those attributes.
Any suggestions?
I would recommend not overloading the usage of these classes to perform logic. This is your service data contract. You shouldn't touch the Silverlight proxy classes that get generated. I recommend that you put your validation logic into other classes that you invoke after deserialization is complete. Otherwise, you might start getting errors in your serialization code when your errors are actually in your data.

Resources