|
OK,
This is the XAML for the Datagrid:
<my:DataGrid CanUserAddRows="True" RowHeaderWidth="10" CanUserResizeRows="False" Margin="235,344,38,93" RowHeaderStyle="{StaticResource RowHeaderStyle}" ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}" HeadersVisibility="All" Name="TenderDataGrid" ItemsSource="{Binding Path=TenderLineItems}" AutoGenerateColumns="False" ColumnWidth="SizeToHeader" IsReadOnly="False" SelectionChanged="TenderDataGrid_SelectionChanged" CanUserSortColumns="False" SelectionMode="Single" SelectionUnit="CellOrRowHeader" IsSynchronizedWithCurrentItem="True" Background="#FFDDDDDD" BorderBrush="#FFAAAAAA" BorderThickness="3" AlternatingRowBackground="LightBlue">
<my:DataGrid.Columns>
<my:DataGridTextColumn Header="Series" Binding="{Binding Path=Series, Mode=TwoWay}" Width="Auto"></my:DataGridTextColumn>
<my:DataGridTextColumn Header="Item No" Binding="{Binding Path=ItemNo, Mode=TwoWay}"></my:DataGridTextColumn>
<my:DataGridTextColumn Header="Description" Binding="{Binding Path=Description, Mode=TwoWay}" MinWidth="200"></my:DataGridTextColumn>
<my:DataGridTextColumn Header="Unit" Binding="{Binding Path=Unit, Mode=TwoWay}"></my:DataGridTextColumn>
<my:DataGridTextColumn Header="Quantity" Binding="{Binding Path=Qty, Mode=TwoWay}"></my:DataGridTextColumn>
<!--<my:DataGridTextColumn Width="5000"></my:DataGridTextColumn>-->
</my:DataGrid.Columns>
</my:DataGrid>
(Sorry about the indentation)
I have a class that defines an observable collection:
using System.Collections.ObjectModel;
using MMSDLL;
namespace Tender_Module
{
class TenderItemModel
{
public ObservableCollection<ITenderLineItem> TenderLineItems {get;set;}
}
}
This is the interface that I use to be able to add Items to the grid:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
namespace MMSDLL
{
public interface ITenderLineItem
{
int RateSize { get; set; }
string Series { get; set; }
string Description { get; set; }
string ItemNo { get; set;}
string Unit { get; set; }
double? Qty { get; set; }
double Rate1 { get; set; }
double Rate2 { get; set; }
double Rate3 { get; set; }
double Rate4 { get; set; }
double Rate5 { get; set; }
double Rate6 { get; set; }
double Rate7 { get; set; }
double Rate8 { get; set; }
double Rate9 { get; set; }
double Rate10 { get; set; }
double Rate11 { get; set; }
double Rate12 { get; set; }
double Rate13 { get; set; }
double Rate14 { get; set; }
double Rate15 { get; set; }
double Rate16 { get; set; }
double Rate17 { get; set; }
double Rate18 { get; set; }
double Rate19 { get; set; }
double Rate20 { get; set; }
double Rate21 { get; set; }
double Rate22 { get; set; }
double Rate23 { get; set; }
double Rate24 { get; set; }
double Rate25 { get; set; }
double Rate26 { get; set; }
double Rate27 { get; set; }
double Rate28 { get; set; }
double Rate29 { get; set; }
double Rate30 { get; set; }
double Rate31 { get; set; }
double Rate32 { get; set; }
double Rate33 { get; set; }
double Rate34 { get; set; }
double Rate35 { get; set; }
double Rate36 { get; set; }
double Rate37 { get; set; }
double Rate38 { get; set; }
double Rate39 { get; set; }
double Rate40 { get; set; }
}
}
Then on my main Window where I define the DataGrid, This is the code I use to set the DataContext:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Data;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using SYSTEM_LIB_DLL;
using SYSTEM_LIB_DLL.Entity;
using Microsoft.Windows.Controls;
using MMSDLL;
namespace Tender_Module
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private ObservableCollection<ITenderLineItem> LineItems = new ObservableCollection<ITenderLineItem>();
private TenderItemModel TM;
private Tender InstanceTender;
private const string COMPANY_NAME = "Infrastructure Systems Integrators - Tender Module";
private int seriesPosition = 0;
private string operation;
private RateHandler InstanceRateHandler = null;
public RateHandler CurrentRateHandler
{
get
{
return InstanceRateHandler;
}
set
{
InstanceRateHandler = value;
}
}
public Window1()
{
InitializeComponent();
this.Title = COMPANY_NAME;
TM = new TenderItemModel { TenderLineItems = LineItems };
TenderDataGrid.DataContext = TM;
MainGrid.Visibility = Visibility.Hidden;
}
This is just the first part of a very large class so I'm leaving out the rest of the class and I'll just show the relevant methods that I use:
Now after i've added a few ITenderLineItems to the grid, i want to add new columns to the grid and set their bindings.
private void CreateRateColumns(int numColumns)
{
for (int i = 1; i <= numColumns; i++)// Iterate numColumns
{
DataGridTextColumn RateColumn = new DataGridTextColumn();
Binding theBinding = new Binding("Rate" + i);
RateColumn.Binding = theBinding;
RateColumn.Header = "Rate " + i + " ";
RateColumn.IsReadOnly = false;
TenderDataGrid.Columns.Add(RateColumn);
}
}
This method is relatively straightforward but what happens is that the bindings don't work on the Datagrid after it has been populated with ITenderLineItems instances. If I create the columns before adding these objects to it, then all is well. Now I'm getting a NullReferenceException on the grid if i enter a text value in one of these Dynamicly created columns' cells. I need this grid to adapt to the settings that the user change as long as the program is running. This is quite a thorn in my flesh
|
|
|
|
|
Hi,
I'm newish to threading & asynchronous development so please bear with me if this is a bit of a n00b question. I would like to cache my proxy client object (in my case called DataServiceClient) to prevent constructing the same class over and over with each data read but I'm thinking that doing this in an async architecture could cause problems (playing with Silverlight, not enjoying the learning curve).
When I subscribe to the response event in my cached object, how would I unsubscribe that specific instance of my method call? Subscribing to events do not give you a unique handle for that subscription, and unsubscribing based on method signature could cause problems as I could use the same method for different things...
Could anonymous methods work for this? Do I need to unsubscribe anonymous methods?
How do I manage the user browsing away form my window before my response event fires (rending my data target non-existent)?
Is there a concise article on the web that I need to read before asking this?
(I really wish they would bring sync calls into Silverlight, I have argued with a number of async fans, and I NEED sync calls)
____________________________________________________________
Be brave little warrior, be VERY brave
|
|
|
|
|
Adriaan Davel wrote: When I subscribe to the response event in my cached object, how would I unsubscribe that specific instance of my method call?
Same way you'd unsubscribe to any event.
The "instance" concept depends on how your handler is defined.
If the handler is static, it is a class handler so it has no access to
non-static members of the class the handler is in. When you remove a
static handler from the event, it doesn't matter which one is removed
since there's no object instance associated with the handler. But then
if you're using a static handler, the same delegate typically will only be
added to the event once anyway.
If the handler is non-static, there is an implicit object associated with
the handler that is added to the event, so in a sense, there IS a "a unique
handle for that subscription". When you add a handler, it is added
in the context of an object of the handling class. If you later remove the
handler from the event, only the handler for the removing object will be removed.
Given that, it's up to you to design your code appropriately.
Adriaan Davel wrote: Could anonymous methods work for this? Do I need to unsubscribe anonymous methods?
Yes and yes. Same rules apply. However, an anonymous method would need to be assigned
to a variable for later removal...is it really anonymous any more if you
do that?
Adriaan Davel wrote: How do I manage the user browsing away form my window before my response event fires (rending my data target non-existent)?
Try it. You'll see your handler(s) will never get called.
Adriaan Davel wrote: (I really wish they would bring sync calls into Silverlight, I have argued with a number of async fans, and I NEED sync calls)
Assuming we're talking about calls from the browser here, like to a web service...
If you NEED sync calls, implement them yourself. Simply block on a
WaitHandle (like an EventWaitHandle) until the handler delegate signals
the event. That's a really bad idea in Silverlight, especially if you
block the UI thread. So instead of blocking the UI thread, you might think
"use a worker thread to wait for completion". Well, that gets just as
complex (if not more) as using async calls, doesn't it?
Nobody NEEDS sync calls...
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Hi Mark, again thanks for the reply, quite a bit to work through
I've worked through an example thats very close to sync calls to WCF in Silverlight, but it still would have been much better to be able to do a true sync call from the UI thread. For example, I create a new instance of a class and send it to the WCF service to save it to the SQL database. In my DAL I get the IDENTITY column value after the insert, and use it as a unique Id on the class (also use it for foreign keys etc). The problem is to get the identity value back across the service (with a return value) and assign the value back to the class instance to ensure that I can use the Id on my client.
I've acheived it with the below (rather elaborate) code block (which also needs a bit of work still), but the problem is that this code HAS to run inside my control event, I cannot abstract it from the control and re-use / recall the same code in other controls as the worker thread needs to invoke the UI code else its not sync anymore...
It would have been so easy to just make a sync call, blocking the UI thread till a response is received, and carrying on, just like Win / Web / WPF can do with WCF calls... The whole concept of preventing the developer from blocking the UI thread during data calls is bizarre to me. (In my uneducated opinion Microsoft is trying to make SL UI as cool / fluent as possible for marketing, at huge expense to "normal" programming methods). I love the fact that async calls are so easy to do, and I believe in async calls, but to make sync impossible is bizarre... I always try to write my code to "look like" the business process / logic, and if you are telling a busines that its impossible to make one process wait for the previous to finish, you'll be thrown out...
Anyway, enough complaining, thanks for the usefull comments, much appreciated
string description = txtDescription.Text;
string name = txtName.Text;
ThreadPool.QueueUserWorkItem(delegate
{
InfonMachineActiveDefinition newInfonMachineActiveDefinition = new InfonMachineActiveDefinition { ContainingBranch = GlobalCache.CurrentBranch, Description = description,
Name = name,
CreatedDateTime = DateTime.Now
};
var channelFactory = new ChannelFactory<IDataService>("*");
var dataService = channelFactory.CreateChannel();
var asyncResult = dataService.BeginSaveInfonMachineActiveDefinition(newInfonMachineActiveDefinition, null, null);
try
{
newInfonMachineActiveDefinition.Id = dataService.EndSaveInfonMachineActiveDefinition(asyncResult);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
if (Dispatcher.CheckAccess())
{
Visibility = Visibility.Collapsed;
if (NewInfonMachineActiveDefinitionSaved != null)
NewInfonMachineActiveDefinitionSaved(this, newInfonMachineActiveDefinition);
}
else
Dispatcher.BeginInvoke(delegate
{
Visibility = Visibility.Collapsed;
if (NewInfonMachineActiveDefinitionSaved != null)
NewInfonMachineActiveDefinitionSaved(this, newInfonMachineActiveDefinition);
});
});
____________________________________________________________
Be brave little warrior, be VERY brave
|
|
|
|
|
maybe, I think I don't understand this code.
What wrong if we call like that?
var client = new MyServiceClient();
client.GetDataAsync( (result) => {
textbox.Text = result;
});
Thanks and Regards,
Michael Sync ( Blog: http://michaelsync.net)
Microsoft MVP (Silverlight), WPF/Silverlight Insiders
|
|
|
|
|
In your example the UI will not wait for the call to the GetData service (since its async) but mine will. In my example the UI code will not run in the same thread as the service call but the UI code will only be invoked after the service call has completed...
____________________________________________________________
Be brave little warrior, be VERY brave
|
|
|
|
|
Adriaan Davel wrote: In my example the UI code will not run in the same thread as the service call but the UI code will only be invoked after the service call has completed...
In my code also, the UI code will be invoked after the service called is completed. For example: textbox.Text = result;
Adriaan Davel wrote: In your example the UI will not wait for the call to the GetData service (since its async) but mine will
I haven't tested your code. The problem with sync call is that it makes the UI to be freezed while waiting for the completion. So, Microsoft decided not to support "sync" calls even a lot of people are requesting it.
So, how does it work with your code? How does the UI wait for the call? Will the UI be freezed while waiting? Or will the progressbar or something be shown? Is there any way to refactor the code so that Silverlight developers can call service sequentially like
service1.GetData();
service2.GetOptions();
Thanks and Regards,
Michael Sync ( Blog: http://michaelsync.net)
Microsoft MVP (Silverlight), WPF/Silverlight Insiders
|
|
|
|
|
Hi Michael,
You are correct, your example will also display the data, I wasn't looking carefully enough
Microsoft's decision to prevent data operations from running on the UI thread is a real mind bender to me, I recon they wanted to protect the reputation of Silverlight from bad developers, so they made it harder for the rest of us. The fact of the matter is that certain things MUST wait for other things (in technology and in business), and the UI needs to be intuitive around the waits, so the UI must wait for certain operations to complete... We are now doing all sorts of jumps & hoops to acheive what is unavoidable...
I'm by no means a threading expert, but to achive your example of service1.GetData(); service2.GetOptions(); in a client side proxy class I think you would have to add a delegate parameter to service1.GetData(); , and after all the code of the proxy method has executed you would invoke the delegate, not sure how you would handle the return values though... There might be other mechanisms to achive this, I'm sure one of the CP experts will enlighten us...
____________________________________________________________
Be brave little warrior, be VERY brave
|
|
|
|
|
Adriaan Davel wrote: There might be other mechanisms to achive this, I'm sure one of the CP experts will enlighten us...
yeah..
In our project, we are sharing the service classes that invoke the WCF proxy between Silverlight and WPF. So, it's really painful and we can't ensure one function does one thing. If we follow one function does one thing then the code will be very messy like this example below with a lot of lambda expression.
void GetAllDogOwners(){
var dogServiceClient = new DogServiceClient();
dogServiceClient.GetAllDogsCompleted += (sender, e) => {
var dogs = e.Result;
var ownerServiceClient = new DogOwnerService();
ownerServiceClient.GetAllOwnersCompleted += (sdr, result) => {
var owners = result.Result;
foreach(var owner in owners){
owner.Dogs = (from dog in dogs
join person in owners
on dog.DogId equals person.OwnerID
select dog).ToObservable();
}
};
ownerServiceClient.GetAllOwnersAsync()
};
dogServiceClient.GetAllDogsAsync();
}
If I make if
void GetAllDogOwners(){
var dogServiceClient = new DogServiceClient();
dogServiceClient.GetAllDogsCompleted += new delegate(OnGetAllDogsCompleted);
dogServiceClient.GetAllDogsAsync();
}
void OnGetAllDogsCompleted(sender, e) {
var dogs = e.Result;
var ownerServiceClient = new DogOwnerService();
ownerServiceClient.GetAllOwnersCompleted += (sdr, result) => {
var owners = result.Result;
foreach(var owner in owners){
owner.Dogs = (from dog in dogs
join person in owners
on dog.DogId equals person.OwnerID
select dog).ToObservable();
}
};
ownerServiceClient.GetAllOwnersAsync()
}
we are thinking to remove all async calls now in WPF..
Thanks and Regards,
Michael Sync ( Blog: http://michaelsync.net)
Microsoft MVP (Silverlight), WPF/Silverlight Insiders
|
|
|
|
|
I think the point here though is semantics, not complexity or limitations.
The fact is, asynchronous doesn't mean you can't have the ui wait.
Doing:
enter
callandwait
leave
vs.
enter
beginasync
showmodaldialogforwaiting
leave
receiveasync
hidemodaldialogforwaiting
leave
Is a similar pattern. In other words, there is nothing to prevent you from locking the UI while you wait for the call. We have several pages that are aggregate controls for filters, locations, and other parameters that act on a grid and all must be pulled in before the user can react. Rather than create the awkward situation of freezing the ui while waiting, in which case the user has to be wondering, "What on earth is going?" We can simply set a global state and then lock down the UI and show a user-friendly animation, loading icon, hourglass, or whatever. As each collection of data comes in, the state is updated and when all controls are fully loaded then we remove the modal "hey, we're initializing" and go on with business as usual.
Would that be something that would work in your case? IMHO even if you need it to logically function as if synchronous, asynchronous gives you more flexibility to engage the user appropriately and notify them you are waiting for something as you pull in the call.
|
|
|
|
|
Yeah, I suppose its down to symatics. Functionally its is indisputable that we want to make the user wait for things before the UI responds to results of conditoins, now we just need to get technical work arounds to acheive the functional requirement.
Your example shows where 3 lines of code could achive the same as 7 lines of code for the same functionality, now imagine what the would look like if you were to do 5 different calls, passing the results from each call to the next, possible passing the same results to more than 1 call, managing the status of each async call could be a pain, and you will have far more code on the CPU & RAM than just doing sync calls...
I might be missing something here, but I do not get MS's decision here...
____________________________________________________________
Be brave little warrior, be VERY brave
|
|
|
|
|
Hi Adriaan,
I know it's been a while since you posted your question, but for anyone else reading this thread I thought I'd mention that it is possible to perform synchronous WCF calls in Silverlight. You just can't do them from the UI thread.
Synchronous Web Service Calls with Silverlight: Dispelling the async-only myth[^]
Whether you should or not is another question. I believe that it is AOK to perform sync calls as long as they are not on the UI thread. Without sync call it is very easy to end up with spaghetti code.
Cheers,
Daniel
|
|
|
|
|
|
Your best bet is to ask in the forum that's under the article. The author understands how his code is supposed to work, and we don't.
Christian Graus
Driven to the arms of OSX by Vista.
Read my blog to find out how I've worked around bugs in Microsoft tools and frameworks.
|
|
|
|
|
I did and like other people, he is not responding. Oh well, I guess I will find something else to use...
|
|
|
|
|
Sorry, I've never used it. I would suggest running his sample and looking for ways your code is different to his sample.
Christian Graus
Driven to the arms of OSX by Vista.
Read my blog to find out how I've worked around bugs in Microsoft tools and frameworks.
|
|
|
|
|
Back in the late 90's Java was main stream and XML was becoming popular, a Sun researcher from China postulated that a Swing or AWT UI could be represented by dumping the widget cache to an XML file and then reconstituted using XML parser and Java Reflections.
I was unable to find the original white paper...
I used this researcher's design pattern on a contract once to create a XML version for winforms.
'Who said good things don't grow under the Sun?'
~TheArch
modified on Friday, July 10, 2009 4:48 PM
|
|
|
|
|
1 - this is not a question
2 - C# is obviously based on Java, so what else is new ?
3 - Sun is so awesome that they come up with these ideas, but can't make money off them. How many quarters have Sun made a profit in, in recent years ?
4 - anyone who is trying to create new technology would be stupid to set out NOT to learn from what people have done in the past.
Forgot to add - XAML is the worst thing about WPF. Too verbose, for one. It's often better to do stuff in code.
Christian Graus
Driven to the arms of OSX by Vista.
Read my blog to find out how I've worked around bugs in Microsoft tools and frameworks.
|
|
|
|
|
Christian Graus wrote: 1 - this is not a question
Hmm, Kinda of thought this was an an implied question. Esp. if you can prove other wise.
Christian Graus wrote: 2 - C# is obviously based on Java, so what else is new ?
Yeah, kinda of, but I think the direct relationship faded around 3.0. 3.5 and 4.0 bring new ideas to the table, and Sun has been playing catch up since Generics.
Christian Graus wrote: 3 - Sun is so awesome that they come up with these ideas, but can't make money off them. How many quarters have Sun made a profit in, in recent years ?
Gotta love those guys, but it makes you wonder how many quarters Stanford's research grants increased...
Christian Graus wrote: 4 - anyone who is trying to create new technology would be stupid to set out NOT to learn from what people have done in the past.
Hmm, I wouldn't say stupid. Pig headed maybe.
Christian Graus wrote: Forgot to add - XAML is the worst thing about WPF. Too verbose, for one. It's often better to do stuff in code.
Well Okay, good point. What about designers? Don't they get to play? Try using Model Viewer Presenter with WPF. Where XAML = Viewer, xaml.cs = Presenter, You'r logic = Model. That might work better.
Wow, you owned an Apple ][!
Did you ever program Beagle Bro's?
|
|
|
|
|
TheArchitectualizer wrote: Yeah, kinda of, but I think the direct relationship faded around 3.0. 3.5 and 4.0 bring new ideas to the table, and Sun has been playing catch up since Generics.
True - but that is kind of my point. Innovation and the replication of good ideas from the past, are not mutually exclusive.
TheArchitectualizer wrote: Wow, you owned an Apple ][!
Did you ever program Beagle Bro's?
Hell, yes. I spent hours reading through Beagle Brothers code and learning from it, I had their posters up on the wall around my computer. I loved those guys.
Christian Graus
Driven to the arms of OSX by Vista.
Read my blog to find out how I've worked around bugs in Microsoft tools and frameworks.
|
|
|
|
|
Me to! My first programing book was Beagle Basic and Pro Dos. The IIe didn't have a clock so my fisrt attempt at programming was a huge sub to count the ticks and update the clock on my BBS with out have to buy a $240 add in board just to tell what time it was. Little did I know I was reinventing multi tasking.
|
|
|
|
|
You can see a demo of my quick and dirty implimentation of MVP in my most recent article:
Big O Algroythm Analyzer for .NET[^]
Q: Would you mind voting on it?
Q: I could use some mentoring, would you be my mentor?
|
|
|
|
|
Christian Graus wrote: 4 - anyone who is trying to create new technology would be stupid to set out NOT to learn from what people have done in the past.
With their upcoming "M" meta-language, I wonder how long it will be before some one make a new declarative curly brace based language.
One which act like XAML but feels like C#!
A train station is where the train stops. A bus station is where the bus stops. On my desk, I have a work station....
_________________________________________________________
My programs never have bugs, they just develop random features.
|
|
|
|
|
TheArchitectualizer wrote: Back in the late 90's Java was main stream and XML was becoming popular, a Sun researcher from China postulated that a Swing or AWT UI could be represented by dumping the widget cache to an XML file and then reconstituted using XML parser and Java Reflections.
And here I was, thinking some idiot at Microsoft just pulled it outa' their ass. In any case, I like my version better because it's a better fit.
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|
|
Uh hua, Uh hua, <nod>, Uh hua, <nod>, <nod>
Interesting bio.
|
|
|
|
|