I have a ListView Binded to an xml file (a simple log file).
This list view is in a secondary dialog Window in my project.
When I open the window for the first time it shows the info in the list view correctly. Then, if I close this window and do some stuff, my xml file changes. If now I reopen the dialog Window containing the xml file, it shows the last status (the info showed the firs time I opened the window), not the whole status with updates.
Why??
The XML doesn't trigger the INotifyPropertyChanged events that WPF databinding relies on to know when items change and need to be re-bound. You may want to set the ItemsSource or DataContext explicitly each time you open the dialog window.
Also, the XML objects don't detect file changes. You may need to reload the XML if you are relying on outside events (system logs?) to create the new XML nodes.
It's hard to tell exactly what will fix your problem because your description is imprecise. You say:
I have a ListView Binded to an xml file (a simple log file).
and this is not actually possible. You can't bind a ListView, only its ItemsSource. And you can't bind to an XML file, but only to an object in memory that contains the data read from the XML file. This sounds like I'm picking nits, but I'm not: the clearer you are in describing what you're actually doing, the easier it will be to provide you with a usable answer.
It sounds as though you probably are defining an XmlDataProvider in XAML with its Source set to the name of the XML file. If you set this as a resource in your main window, it's going to be loaded when the main window is loaded. If your child window has something like
<ListView ItemsSource="{StaticResource MyXmlDocument}" .../>
it's going to look up the XmlDataProvider using the resource dictionary's Find method, and find it in the main window's resource dictionary. You can close and reopen the child window all day long and the XmlDataProvider it uses won't change.
If this is the case, what you probably need is one of two things.
First, you could move the definition of the XmlDataProvider resource to the child window's XAML. That will force the child window to reload the XML every time the child window loads.
Second, you could add a method to the main window that recreates the XmlDataProvider whenever the XML file changes on disk. (How you know when the XML file changes, and how you trigger the method in the main window, are relatively tricky problems to solve - you could use FileSystemWatcher events, for instance.) You'd need to use the DynamicResource markup extension in your child window XAML if you do this.) That will refresh the child window every time the XML file changes - even if it's already open.
Related
Hi I have a really strange effect here:
I have a main window, which content is filled with a complete visual tree containing the form presentation.
First form to show is the Parent form, which allows to call a child form.
When I load the child form, the Parent is basically backup up into a stack, then the new content is set to the window.
When I close the child form, the backuped up parent is set back as the window content and the child window is dropped.
Now for the problem:
I load a collection of objects into a listbox.
The listbox uses textblocks for displaying the objects' properties
(FirstName, LastName, PhoneNumber,MobileNumber, Email), and after each textblock, a comma is contained in the Xaml to separate the entries.
BUT: if a textblock is empty, the corresponding comma must not be shown, like below:
I managed to do this using a converter that anaylses which commas to show.
This work perfectly, but when I show a child form and closes it, the display is corrupted regarding comma visibility:
I made two observations:
The corrupted display only happens when I have a UI Culture
different form en-US (de-DE in my case)
I placed some traces in the
converter code and I see that the converter is called after opening
(and closing) the child form when I use de-DE, but not when I use
en-US.
Is there any idea what can cause such effects? And how I can get around them?
Regards
Finally, I found that setting Window.Language was the problem.
I do this in the mainwindows constructor:
this.Language = System.Windows.Markup.XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentUICulture.Name);
This is necessary to get correct display for numbers for example.
But now I issue the following block, and all works in all cultures. [During startup, I check the default Ui culture, and if I set it to any other, I set App.CultureChanged accordingly]:
if (!App.CultureChanged )
FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
this.Language = System.Windows.Markup.XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentUICulture.Name);
I have an ItemsControl control. In its items I show a lot of things: images, textblocks, etc.
I have a 'Search' functionality implemented on the itemscontrol - meaning that if the user enters some letters from the keyboard, the items control will be refreshed. My Search method is in code-behind and it takes less than a second. However, the time between I enter the letters and see the results is 3-4 seconds. I have a window closing command and I want to put it in the exact moment before showing the search results. If I put this command in the end of my Search method (in the code-behind), there is still a few seconds delay between closing the window and showing the items. I'm thinking that the binding is slow and that's why i need to catch the event that gets called when the binding finishes. Is there such an event in WPF?
OnPropertyChanged event gets called before the Search methods finishes, so that doesn't help me.
I also tried with the OnDataContextChanged event, but it gets called just once - when the control is initialized. I need it to also get called when the user enters letters and new binding occurs.
When you establish a data binding between a source property and a target dependency property in WPF, this Binding is actually translated into a BindingExpression object which does the heavy lifting of updating the source and the target at the appropriate moments.
Unfortunately, BindingExpression does not provide events when something is updated, as you can see here: http://msdn.microsoft.com/en-us/library/system.windows.data.bindingexpression(v=vs.110).aspx
The only way is to set the UpdateSourceTrigger to Explicit when you define your binding, get the binding expression in code behind and update the source and target manually - then you have full control and can encapsulate your common functionality in this scenario.
You can obtain the BindingExpression by using the BindingOperations.GetBindingExpression static method: http://msdn.microsoft.com/en-us/library/system.windows.data.bindingoperations.getbindingexpression(v=vs.110).aspx
If you have any further questions, please feel free to ask.
P.S.: isn't there maybe another way to do this? If you're using a source collection that you bind to your ItemsControl, couldn't you perform the searching / filtering operations on the source collection and just let the collection binding update your ItemsControl?
I am writing a program that overlay's a toolbar onto another applications window. I am able to iterate through the MDI child windows and even access all the controls via PInvoke. The one thing I am trying to figure out is how to get the controls actual Name property.
I am able to see the name of the field using Hawkeye but I cannot figure out how it is getting the control name.
One thought is that it may be injecting something into the target application and running something like Control.FromHandle but I am not 100% sure.
Thanks for any help.
Unfortunately, the Name property of a control is a property of the .Net object that creates the window not of the control window itself. There is no way to get this value using the window handle - PInvoke or otherwise - from outside of the process.
You would need to do some variation on what Hawkeye appears to do. Attach to the process, examine the object hierarchy and/or inject code dynamically using the CLR Debugging API.
I want to add/remove some part of XAML dynamically i.e. from code behind file in C#.how to Add any specific XAML string on specified location (means under some tag) from .cs file. Please help.
XAML is xml you can use XmlReader and XmlWriter or any other of the XML serialization mechanismn of .NET to write/read XML (XMlDocument is probably the best approach here to modify existing xml). ALso there are the XamlReader and XamlWriter class that allow ou to (de)serialize any object graph from/to XAML automatically. If you can use .NET 4.0, you have even more fine grained possibilities to athor XAML because it has a new XAML stack. Use this as a starting point.
What is it that modifying the XAML will do for you?
If you just want to change the appearance of your WPF application (perhaps by adding some more content at certain locations), it will most likely be easier to do this by referencing the objects in question. So, if you need to add some text to a button, name the button with x:Name="myButton" and in code set: myButton.Content = "Click Me"
XAML is really a technology for constructing object hierarchies. Pretty much every element in the XAML corresponds to a .NET CLR class. When loaded, these classes are instantiated nd populated according to the attributes used in the XAML. Once loaded, the XAML has finished it's job and is essentially unloaded/unavailable.
You might need to do something beyond this, but from your brief question it doesn't seem like it. I would just work on the object model and leave the XAML be.
I'm in the process of teaching myself WPF, and I have run into a small issue that I can't find the answer to.
My test app allows image files to be dropped into a StackPanel. Once an image is dropped, a new user control is added to the stack, and displays some meta-data about the file. All is working correctly, and I can iterate through the child controls to retrieve the values.
What I'd prefer to be able to do is allow the user to persist this data to a file, so they can suspend working on the data. The obvious way for me to do this is to store the data in a DataTable and serialise/deserialise it to xml. However, I don't know how to drive the collection of user controls from a DataTable or DataSet object - in fact, I don't even know if this is the right way to go about it in a WPF app. I am more than willing to admit my ignorance here and take better suggestions if there are any.
Summary of the app logic.
1) File is dropped (from Win explorer) onto a StackPanel
2) File triggers creation of a new user control, which is added to the StackPanel
3) Data is populated in the user control
4) Processing data involves iterating through the control collection.
What I'd like
1) File is dropped (from Win explorer) onto a StackPanel
2) File data is inserted into some persistable object (data table?)
3) updated data table drives the generation of the user control to be added to the displayed collection.
4) save / load functionality persists the data for re-use later.
Thanks in advance
You're on the right track with the second approach, what you need to look at is the ItemsControl - that's a thing which can have items added to it. It's the base for ListBox etc, and you can template it to work as you require. Then there's the DataTemplate which handles which controls are displayed and data binding to those controls when an item is added to the underlying data structure. There are quite a few examples around on the net, try Dr WPF.
In order to make everything work the underlying data structure must support change notification. As everything happens automagically, once the Xaml is setup, you can find yourself in an odd situation. You've added data to a data structure, which in turn has caused controls and data to appear in your ItemsControl. How do you link the data items and their visual controls. The answer is to use some built in static methods ItemFromContainer which links from the graphic to your underlying data item, useful to handle click events, and ContainerFromItem which does the reverse.