I'm trying to use the code from the following sample:
http://msdn.microsoft.com/en-us/magazine/dd569761.aspx
to dynamically create FlowDocuments with a table bound to xml.
The problem is that I first load the template and only then set the Databinding (because I use different data each time).
Anybody knows how to modify the code (maybe react to another event?) to make the code
from this example trigger code generation after the "dynamic" datacontext is set?
Thank you in advance
Ah, so you are using the 'BindableRun' class and are never getting bound? I recently encountered the same problem. You can trigger the data binding by updating the layout on any 'UIElement' object tied to the same dispatcher. The object does not even need to be in the visual tree - it is just invoking the context layout manager shared by all objects using the same dispatcher.
Simple example:
Button b = new Button();
b.UpdateLayout();
To get an accurate page count from the document paginator, you should update the layout first. Be careful though, as updating the layout again later will also invalidate any document paginators tied to the same dispatcher.
Related
I have a project that gets data from a database and binds that data to some elements in xaml. I have added a button that fetches new data from the database and want to refresh the data bound elements in the xaml.
Now, I know the proper way of doing this is to implement the INotifyPropertyChanged events in the data class but I wanted to avoid this as there are so many properties. I figured out that simply calling 'this.DataContext = data;' after I have retrieved the new data from the database updates the binding in xaml.
Can anyone tell me what is wrong with this method?
Thanks!
Quite simply, if you don't want to implement the INotifyPropertyChanged interface, then don't use WPF. WPF is quite often a verbose language... it took me a while to get used to this. While there are mechanisms like Converters, Styles and Attached Properties that enable us to reuse code, you will often find yourself writing code that you've written before. Just get used to it, or change languages.
To summarise, you can't write effective applications in WPF without implementing the INotifyPropertyChanged interface.
If you don't use INotifyPropertyChanged interface you don't allow the binding mechanism to work since it wont know of any changes of your data.
The data binding is one of the most powerful tools in WPF if you dont use it you will have to write the propagation of the data changes between you model and the UI yourself like it was done in Winforms....
if its too hard to write the implementation for each property of each class in your than you can create a code snippet.. like prop/propdp
I've got a new Problem here. I've got a MainWindow in which is a ContentGrid and in this is a Frame. Now I've created different Pages which can be shown in this "content-area". In One of these pages there is a Datagrid bound to a CollectionViewSource which Source is a Database (via EntityFramework). Now, when a Change on this Database-Table happens (solved via ServiceBroker and SQLDependency, firing works fine) The Datagrid have to update.
Now the Problem:
The "Dependency_OnChange"-Event is working in the MainWindow-Thread. When i try to access the CollectionViewSource of the Page to Update it (cvs.View.Refresh) i get an Exception that this is not possible because of another Thread which own this CVS.
I've tried it with different Dispatching like:
Application.Current.Dispatcher.Invoke((Action)(()=>
{
cvs.Source = _db.Table.OrderByDescending(nr => nr.Date).Take(200);
cvs.View.Refresh();
}));
This Codeblock doesn't brings an Exception but i wont update the UI too... It seems that it does nothing.
Can anyone help me?
You data grid will update if your LINQ query evaluates. Right now it just specifies the LINQ IEnumerable but is not evaluating it.
cvs.Source = _db.Table.OrderByDescending(nr => nr.Date).Take(200).ToList();
should do the evaluation of the LINQ for you...
Although I must say your cvs.View.Refresh() call is very expensive as it causes entire grid to refresh. You may have to consider a better design here.
Why dont you set the dataGrid.ItemsSource = _db.Table.DefaultView as the item source to the datagrid directly. I guess if your table updates (and peforms _db.Table.AcceptChanges();) the view would automatically notify the changes to the grid and grid would possibly update itself faster!
But thats just my opinion as I am not aware of your threading context here. But still do try and let me know.
I have this:
Shows a waiting animation to 'block' the UI while performs a loading operation in the background.
At the end of the loading I call a method that instances a User Control and displays some data by using Bindings (and ObservableCollection among others)
This User Control gets displayed and user can interact with it, however the ObservableCollection seems to be stuck in another thread as it doesn't allow to add new items to it.
I've tried to update the UI at the Completed event of a BackgroundWorker, using Dispatcher, using DispatchTimer... all of this displays the User Control, but the ObservableCollection stays of out reach for adding.
The code that tries to add items to the collection is inside the UserControl.
The exact error is: "This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread"
This does not happen if I don't do the loading in the background.
Thank you for any workaround for this.
By the way, trying to add the items using Dispatcher doesn't work either.
In other words, what I would like to do is to create an object in the UI Thread while being in the background... I know this may sounds silly.
You may have to check which Dispatcher you are using? In your case you could be referring to two different dispatchers.
Also why not use thread safe observable collection?
Usually I will create the objects on my UI thread, then populate them with data obtained from a background thread.
For example,
void async LoadButton_Clicked(object sender, EventArgs e)
{
MyCollection = new ObservableCollection<SomeItem>();
// Can also use a BackgroundWorker
var collectionData = await GetCollectionData();
foreach(var item in collectionData)
{
MyCollection.Add(item);
}
}
I'm using C# 5.0 async and await keywords for asynchronous operations, but you can also use a BackgroundWorker that does your background work.
You can also use Dispatcher.BeginInvoke() for some lighter background work (such as copying data into MyCollection), although for heavy work I find it still locks up the UI so I prefer to use background threads.
It is not possible to modify the contents of an ObservableCollection on a separate thread if a view is bound to this collection, instead you can override ObservableCollection and provide support for it and use it across your application.
This sample contains exactly what you want - http://tomlev2.wordpress.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/
When it comes to threads and ui-elements one of the most important rules to follow which may safe you a lot of trouble in the long run is to keep ui-element instantiation on the ui-thread. Surely you can manage that. And if you need to change those objects from another thread you can use the Dispatcher.
(The threading model reference may also be of interest)
Thank you everyone for your help... a guy from MS visited the company (sorry for the commercial annotation) to do other things, I stoled him and show this behavior. In a matter of 2 minutes founds the source of the problem... which I'm not sure to really understand.
It happens that I'm using an ICollectionView to display a sorted/filtered version of my problematic ObservableCollection. I was creating this ICollectionView in the constructor of my class, so at the moment of deserialization it was created in another thread. He suggested to move this creation to a further time in code (when the related property gets read). This solved the problem.
However the ObservableCollection, created in that other thread, now lets me add new item. Not sure why, but now it works.
Sorry for being this late and thank you again.
I have a winform that needs to be loaded to update its controls' values or properties, before it is to be shown.
I found a stackoverflow question asking the same thing, but it's answer doesn't really help me. Load a form without showing it
Any sample code will be appreciated. Thank you,
Only you need create a new instance of the form and set the values of the controls.
check this code
Var
AForm : ChildForm;
begin
AForm:= new ChildForm;
AForm.textBox1.Text:='Foo'; //this control can be accessed here because the Modifiers property was set to public.
AForm.Show;
end;
Btw remember if you want modify or access the controls of another form you must set the property Modifiers of the control to access to public.
Create the form like this:
form := new MyForm();
Assuming you have implemented a method on MyForm to update the values, call it:
form.Update();//may need to pass parameters here
Show the form in the usual way:
form.ShowDialog();
From MSDN:
Form.Load
Occurs before a form is displayed for the first time.
So you can do all updates to the controls that are necessary before you show the form in this event handler.
But actually it is probably better to use databinding on the controls, so that they automatically reflect the current values you want them to show and you don't have to write any glue code bringing data on controls (and reading from them).
I am using observable collections all around my applications. My problem is that when i use a popup window for editing those entities, my bound lists are getting changed when the user changes those corresponding fields in the window.
How could i simply freeze the observable changes norifications, and release them only when the entity is saved?
Thanks,
Oran
I think the issue is not with the collection, but with the entities themselves. ObservableCollection raises an event when an item is added or removed, not when a property of an item is changed. This part is handled by the INotifyPropertyChanged implemented by the item, so it's this notification you need to disable.
I suggest you have a look at the IEditableObject interface, which is designed for this kind of scenario. You can disable the notifications in the BeginEdit method, and reenable them in EndEdit and CancelEdit.
EDIT: Paul Stovell has a nice implementation of an IEditableObject wrapper here :
http://www.paulstovell.com/editable-object-adapter
You can use:
BoundPropertyOfViewModel = CollectionViewSource.GetDefaultView(AgentDeploymentDetail);
and bind to the view instead of binding directly to the ObservableCollection. This is the same object that allow you to filter/sort your output without touching the collection.
When you want to stop changes, use DeferRefresh(). When you are done, call Refresh().
WARNING
This will not pervent showing of changes in each item itself, only the list.
You could make a deep copy of the object you want to edit. This way, you can act on the copy while editing, without interfering with the original that remains in the list. Once you`re done editing, you can replace the original by the edited version or rollback.
All the anwers above are great. but i found a good and convinent prodedure to perform the desired in an efficient and clean way. It is based on performing a deep copy on a detached object, using Matthieu MEZIL entity cloner ( http://msmvps.com/blogs/matthieu/archive/2008/05/31/entity-cloner.aspx ).
For full details please check out the followings : Entity Framework Attach Exception After Clone
Thanks for all the great support...