Troubles with ObservableCollection<T> in Silverlight client - c#

I've got a solution with a WPF client, a WCF service and a Silverlight Client (SL 4).
The WPF client works smoothly but the Silverlight is acting up on a point which I'm not sure how to handle it.
These are snippets of the code I have in Silverlight:
using sl_HFClient.svc;
namespace sl_HFClient
{
public partial class MainPage : UserControl
{
svc.IhfsvcClient dataSrv = new svc.IhfsvcClient();
ObservableCollection<svc.ReasonData> reasonData;
}
This is to set everything up, next comes the call to the service:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
dataSrv.wcGetReasonsCompleted += ReasonsLoaded;
dataSrv.wcGetReasonsAsync();
}
And at last, the code to get the collection and bind it to a combobox:
private void ReasonsLoaded(object sender, wcGetReasonsCompletedEventArgs e)
{
reasonData = e.Result;
}
However, this returns the following error:
Cannot implicitly convert type 'sl_HFClient.svc.ReasonData[]' to 'System.Collections.ObjectModel.ObservableCollection'
I'm quite new to Silverlight and C#, I've done some things with SL4 and VB.NET before and
by comparing this code with a VB.NET project it seems to work.
What am I doing wrong??
//JaggenSWE

Try the following:
private void ReasonsLoaded(object sender, wcGetReasonsCompletedEventArgs e)
{
reasonData = new ObservableCollection<ReasonData>(e.Result);
}
Not entirely sure if this will work in Silverlight, but the solution nonetheless is to explicitly create a new ObservableCollection<ReasonData> instead of trying to implicitly cast from an ReasonData[].

Related

Sharing instances and methods/variables within a form in c#

I'm very new to c# and just started to use forms to create a GUI.
Here's some code:
public void Server_connect_button_Click(object sender, EventArgs e)
{
//Open CasparCG server connection and create a TCP client
int port = portnumber;
TcpClient serv1 = new TcpClient("localhost", port);
}
public void Disconnect_server_button_Click(object sender, EventArgs e)
{
serv1.Close();
}
This is code from a couple of button implementations within Form1.cs.
The problem I have is that the serv1 instance in the Disconnect_server button code is not recognised. So the instance is not making it's way out of the Server_connect code. I've tried using the same code (as well as variables and methods) within the Main() code in Program.cs but I'm unable to get any recognition of any of these outside of the same block of code into the button code so I'm clearly overlooking something. I've tried making everything public etc. but it all seems to make no difference. Nothing seems to communicate variables/methods/instances anywhere else in the code.
Please realise I'm a beginner with this language so I'm sometimes getting stuck on this (presumably) basic stuff.
Thanks,
Martin
Issue is Variable Scoping , right now variable scope is upto the method Server_connect_button_Click, you need to increate scope of variable at class level
For providing instance to all you method in given class you can do like this
class Abc {
private TcpClient serv1;
public void Server_connect_button_Click(object sender, EventArgs e)
{
//Open CasparCG server connection and create a TCP client
int port = portnumber;
serv1 = new TcpClient("localhost", port);
}
public void Disconnect_server_button_Click(object sender, EventArgs e)
{
if(serv1!=null)
serv1.Close();
}
}
What I mean to say is you need to declare variable at class level to resolve your issue, the current problem with your code is scope of a variable is up to given method only

Subscribe to event in dll from another application

I've been looking all over for a possible solution, but none seem to come close to what I actually need. I have a windows form which outputs to a class library (dll). I reference this dll into a console application and then launch the GUI in the dll. I want to be able to subscribe to a control event and do what ever code in my console application.
I have no problem when I want to read or write properties in the dll directly from my console app. Example:
MyDll.MyClass myObj = new MyDll.MyClass();
myObj.Textbox1.Text = "Hello World!";
However, I would like to subscribe to the TextChanged event in my dll and output the new text to my console app. Something along the lines of:
public void textbox1_TextChaned(object sender, EventArgs e)
{
Console.WriteLine(myObj.textbox1.Text);
}
Is there any way to subscribe directly to that event? or some other event?
Set the modifier of textbox1 to public
Subscribe to the TextChanged event:
myObj.Textbox1.TextChanged += textbox1_TextChaned;
The following code in a console app works for me. I'm referencing a Windows Form Application rather than a DLL, but I don't think there should be much difference:
class Program
{
static WindowsFormsApplication1.Form1 frm;
static void Main(string[] args)
{
frm = new WindowsFormsApplication1.Form1();
frm.textBox1.TextChanged += textBox1_TextChanged;
System.Windows.Forms.Application.Run(frm);
}
static void textBox1_TextChanged(object sender, EventArgs e)
{
Console.WriteLine((frm.textBox1.Text));
}
}
This doesn't answer your question directly, but it will solve your problem in a neater way, IMO.
In your DLL define an interface (IEventProcessor).
In your console
application implement the interface (ConsoleEventProcessor).
Pass an instance through the constructor of the form
call its methods from the events in the form.
In the console app:
IEventProcessor processor = new ConsoleEventProcessor();
MyDll.MyClass myObj = new MyDll.MyClass(processor);
Then in the form:
IEventProcessor _processor;
// constructor
public MyClass(IEventProcessor processor)
{
_processor = processor;
}
public void textbox1_TextChaned(object sender, EventArgs e)
{
// pass whatever parameters you need to use in the method
_processor.ProcessText1Changed(textbox1.Text);
}

UI Forms events block my other STOCK TICKER API events - how can I prevent this?

I have an API (dll) that collects stock ticks via an event mechanism. Such as below:
...
using MT4API;
public partial class Blue : Form
{
...
public Blue()
{
...
string symbol = "GBPUSD";
MT4DDE dde = new MT4DDE("");
dde.OnQuote += new System.EventHandler<QuoteEventArgs>(MT_OnQuote);
dde.Connect();
dde.Subscribe(symbol);
....
The idea is that on each chart tick I get an event. here is the event handler code:
private static void MT_OnQuote(object sender, QuoteEventArgs args)
{
GlobalClass.Ask = args.Ask;
GlobalClass.Bid = args.Bid;
// I have back ground worker code that updatestables from the global class
}
This all works fine. So long as I do not touch any other buttons on the form UI. As soon as I click a button on the form of the UI... I no longer receive events from my API, the UI application functions normally, but with no data from the API.
Why do events from the UI stop any further events coming from the API event?
Any idea whats going on here? Or suggestions how to design this?
Does the same problem occur if you comment out your code that updates the tables from the global object? and if you comment out the background worker?
It would be a good idea to distinguish if the event stops being fired just after you press some button on the UI, or if it stops being fired only after some line of code you wrote is being executed.
In order to be able to help you, we would need to know how the event on the MT4DDE class is triggered.
If you have the code for this class, posting it would help.
If you don't you may want to use a tool such as Reflector to decompile the assembly into C# and see what the MT4DDE class is doing that might cause it to stop invoking the event.
In addition, if you are doing anything related to background threads, or if you're doing anything unusual with your application's main message loop, it would be a good idea to mention it here.
I have tried to use the invoke command, it works, but after a few events it stops...here is the code isolated:
using MT4API;
namespace WindowsFormsApplication1
{
public delegate void UpdateTextCallback(double ask, double bid);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
string symbol = "GBPUSD";
MT4DDE dde = new MT4DDE("");
dde.OnQuote += new EventHandler<QuoteEventArgs>(MT_OnQuote);
dde.Connect();
dde.Subscribe(symbol);
}
private void updateTickDisplay(double ask, double bid)
{
textBox1.Text = ask.ToString();
textBox2.Text = bid.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
private void MT_OnQuote(object sender, QuoteEventArgs args)
{
BeginInvoke(new UpdateTextCallback(this.updateTickDisplay),
new object[] { args.Ask, args.Bid });
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
textBox3.Text = textBox1.Text;
}
}
}
The only difference from the real code is that I am using a data grid....as opposed to a text field. But it is clear that the UI blocks somehow the new events. It is strange that I get about 5 to 10 events and then it just stops. Strange. Any ideas on a differnet design?

Attaching method to execute for an Event

I got an event from special API I'm working with, the event I'm working with is defined as
public event EventHandler<QuoteEventArgs> OnQuote
public class QuoteEventArgs : EventArgs
so what I'm trying to do is attach a method to run when I got a new Quote listening to this event.
so what I do is:
myInstance.OnQuote += new EventHandler<QuoteEventArgs>(doThis);
And the method is defined as:
public void doThis(object sender, QuoteEventArgs e){
//code here..
}
The error I get is:
Cannot implicity convert type 'System.EventHandler<MT4API.QuoteEventArgs>' to 'System.EventHandler'
but I don't seem to have a special eventHandler on the API either, so not quite sure how to make that work.
From the comment discussion, it appears that you are using a version of the library in which the event does not have a generic type, i.e. the signature is
public event EventHandler OnQuote;
This means you will also have to consume it in a non-generic way:-
myInstance.OnQuote += new EventHandler(doThis);
public void doThis(object sender, EventArgs e){
var myArgs = (QuoteEventArgs)e;
...
}
My guess is that there are two classes with the name QuoteEventArgs, perhaps one from a referenced DLL and one from a generated proxy. Ensure that if you've got usings that the usings are correct.

problem with RX and web service collection loading wp7

I'm beginner with C# and wp7 platform and I have some problem with good idea to get request from web service.
I made webservice in PHP (nusoap - WSDL) and everything is working fine in "normal" using.
Now I have ObservableCollection saved in IsolatedStorage with I load when Page is open (List of watched stacks exchange). Then I want to refresh data for every item from web service.
I don't know whether this is a good idea.
Code:
private GPWWebservicePortTypeClient client = new GPWWebservicePortTypeClient();
private ObservableCollection<WebServiceClass.ItemGetValues> StoredStock =
new ObservableCollection<WebServiceClass.ItemGetValues>();
public const string _fileName = "listaObserwowanych.xml";
public Page()
{
InitializeComponent();
DataContext = App.ViewModel;
this.Loaded += new RoutedEventHandler(Page_Loaded);
client.GetLastValueCompleted +=
new EventHandler<GetLastValueCompletedEventArgs>(client_GetLastValueCompleted);
foreach (var itemGetValuese in App.ViewModel.Items)
{
client.GetLastValueAsync(itemGetValuese.name);
}
var o =
Observable.FromEvent<GetLastValueCompletedEventArgs(client,"GetLastValueCompleted")
.Subscribe(setList);
}
void client_GetLastValueCompleted(object sender, GetLastValueCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(Convert.ToString(e.Error));
}
else
{
ObservableCollection<WebServiceClass.ItemGetValues> ListValues =
(ObservableCollection<WebServiceClass.ItemGetValues>)
JsonConvert.DeserializeObject(e.Result,
typeof(ObservableCollection<WebServiceClass.ItemGetValues>));
StoredStock.Add(ListValues[0]);
}
}
private void setList(IEvent<GetLastValueCompletedEventArgs> ex)
{
List.ItemsSource = StoredStock;
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
App.ViewModel.LoadData();
List.ItemsSource = App.ViewModel.Items;
}
Like u see I use RX to call method client_GetLastValueCompleted add store result to auxiliary variable (StoredStock). Then refresh List in setList method, but that method is client_GetLastValueCompleted what is not soo good idea, becouse I need to run that method only when all of runned GetLastValueAsync in foreach is completed.
Second problem: becouse of async web service method StoredStock sometime have different order than App.ViewModel.Items .
Any good idea how to do that in right way?
Best regards,
Lukas
You're really mixing up a number of ways to call web services and Rx. You really need to decide on a single way and stick to it.
If you're going to use Rx, then you'll have something like this:
public Page()
{
InitializeComponent();
DataContext = App.ViewModel;
this.Loaded += new RoutedEventHandler(Page_Loaded);
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
App.ViewModel.LoadData();
var storedStock =
new ObservableCollection<WebServiceClass.ItemGetValues>();
List.ItemsSource = storedStock;
var values =
Observable.Using<WebServiceClass.ItemGetValues, GPWWebservicePortTypeClient>
(() => new GPWWebservicePortTypeClient(), ws =>
{
var clientGetLastValue = Observable
.FromAsyncPattern<string, GetLastValueResponse>
(ws.BeginGetLastValue, ws.EndGetLastValue);
Func<string, WebServiceClass.ItemGetValues> deserializeFirst = r =>
((List<WebServiceClass.ItemGetValues>)JsonConvert
.DeserializeObject(r,
typeof(List<WebServiceClass.ItemGetValues>)))
.First();
return
from item in App.ViewModel.Items
from e in clientGetLastValue(item)
select deserializeFirst(e.Result);
});
values.Subscribe(storedStock.Add);
}
You'll have to get the right method call names for your web service client, but the code should roughly be right. Let me know how you go.
I corrected the code above. Should have returned the query inside the Using call rather than assign it to values.
I corrected the call to FromAsyncPattern to use the correct method names and return type from the actual web service reference class sent via email.
It should look like this:
Observable.FromAsyncPattern<string, GetLastValueResponse>
(ws.BeginGetLastValue, ws.EndGetLastValue);
If you're a beginner with C#, try to avoid RX for the time being. It is a cool technology, but if you use it without clear understanding of what is going on, it will bring more problems than solve.
Use a simple event, and when each async item arrives, locate and update the correspondent one in the stored list.

Categories

Resources