wpf converter culture != en-US - wpf

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);

Related

Detect unpost of ttk::combobox

I have a Tcl/Tk program. In it I have a combobox, like so:
set cb [ttk::combobox .cb -state readonly -textvariable selection -postcommand [list choices .cb]]
The proc choices runs when the combobox posts, which is what I want. My question is, how do I detect when the combobox unposts?
I've tried both binding on <<ComboboxSelected>> and setting a variable trace on selection. The problem with each is that they only fire when the user actually changes the selection. I need some way to always detect when the combobox unposts.
Thanks!
edit
What I'm trying to accomplish: When the combobox posts it presents the user with a list of options. I don't expect the user to know what the options mean, therefor I am highlighting the options visually in a different area of my program. I have this highlighting triggering and working well with -postcommand. The issue is to know when to turn the highlighting back off.
<<ComboboxSelected>> doesn't fire if the user doesn't change the selected value.
<Leave> and <FocusOut> fire too soon (e.g. as soon as the box posts).
The combobox's popdown is actually its own nest of windows, and if your combobox is called .cb then the popdown has the imaginative name .cb.popdown (note that this implementation and is not guaranteed). If you add a binding to that widget's <Unmap> event you'll get to see the unposting; <Unmap> events are exactly the notifications sent when a window ceases to be displayed in the virtual desktop layer sense (as opposed to just ceasing to be visible, say because there's another window on top; there's events for that too, but they're not cross-platform).
The tricky bits:
The popdown is usually created when needed, i.e., the first time it appears. You need the window to exist (but not necessarily be visible) before you bind to it. You can get the handle of the popdown widget with ttk::combobox::PopdownWindow, which will make the widget if it doesn't already exist. (It's part of the implementation, but it is more likely to be stable than the name.)
set popdown [ttk::combobox::PopdownWindow .cb]
bind $popdown <Unmap> {yourCallback %W}
It is possible to dig around within the internal arrangement of the popdown, but I don't recommend it; it's much more likely to change without warning.
Binding to the toplevel has the usual issues with events also being delivered for subwindows. Your callback should check that the event it has been given is actually for the toplevel:
proc yourCallback {w} {
if {$w ne [winfo toplevel $w]} { return }
# The rest of your code here...
}
The window name of the listbox used by ttk::combobox is:
set popdown [ttk::combobox::PopdownWindow .combobox].f.l
I believe this is what you need.
bind <Leave> $popdown mycommand

WPF Printing multiple pages from a single View Model

I am currently a little bit troubled by the following problem. I have a user interface which basically shows a graphic (a canvas made of Lines, Circles, ... these are all WPF objects). Depending on the selection a user makes in the menu, some items get deleted and some get added. So the basic image looks the same, but a few modifications are made.
The user has the possibility to select - say - 10 different "pages" by clicking a Next/Previous Button.
I am using MVVM Light and my ViewModel contains all the items of the graphic (all Lines, ...).
Now I would like to print that graphic to multiple pages. The first page should contain the graphic with changes from page 1, the second page contains the graphic with changes from page 2 and so on. The actual number of pages is dynamic. I track this with a property CurrentPage and a property PagesTotal.
Whenever I push the "Next" button, this causes a command to be executed which will change the variable CurrentPage and also makes sure that the correct items are displayed.
Now I would like to print this but this is where I'm stuck. I dont' mind leaving the MVVM zone and doing some dirty work in code-behind but I would refuse to draw everything again like in the old GDI days.
Any ideas are really welcome.
Create a UserControl containing your display logic (you graphic, for instance). Grab you ViewModel list and project then in UserControls, setting each ViewModel as each UserControl's DataContext.
Force each one to render calling Measure with infinite value and then Arrange with the resulting DesiredHeight and Width. Then follow the procedures to print WPF visuals (link link link).
Essentially, this should be quite simple if and only if your views work independently; i.e. your ViewModel doesn't contain UiElements that are placed into your View.
Simple solution is to basically print your visual root. If need be encapsulate your Views in a user control first.
PrintDialog printDlg = new PrintDialog();
UserControl1 uc = new UserControl1();
printDlg.PrintVisual(uc, "User Control Printing.");
Reference
Alright, I have to admin that I now switched back to doing the printing through code only. I would have really liked doing it "WPF-style" but handling the multiple pages issue was just too much trouble.
Anyway, there is still one issue regarding the printout left but this will be another question.

How can I intercept the text property on a control inherited form a WPF TextBox?

What I want to do is intercept assignments to the Text property on my control inherited from a TextBox. I the want to modify this text and have the modified text shown in the text box. I aslo need the ability to return something different from what is shown in the text box when the property is read. In Win Forms I could do this by overriding the Text property as it was declared virtual. Obviously things are a bit different with dependency properties. One idea I had was to use OverridePropertyMetadata to have my own callback detect the property change and then call the original callback obtained with GetMetadata. This doesn’t work as property changed callbacks are merged. I’d be interested if there is another way to do it which is specific to this property but I like to find out if it is possible “override” dependency properties in general.
My application is a formatted text box when the text is set to 1000 say (for a numeric format), the text box shows 1,000 but when you read the text you get back 1000 again- the box will keep track of the un formatted text internally. I managed to implement in Win Forms fairly easily but am now trying to port it to WPF.
I think OverridePropertyMetadata is the way to go, but rather than defining a new PropertyChangedCallback, you could write a new CorceValueCallback:
static object CoerceText(DependencyObject d, object baseValue)
{
string s = (string)baseValue;
// Change s to whatever you want
...
return s;
}

Tool to know Windows Form Application's Form fields

I am working on a WinForm Application.
The Form has many fields/components but is poorly built.
for example a field is used as user name on one case and used as folder path on the other case. Code is quite poorly maintaned.
Is is possible that when i run the application and GUI appears, i can use a tool like 'spy++' which can show me 'names' of the components (not ids). For instance the name of a button or name of a label.
Or if i can use SPY++ for 'names' please tell me?
I would solve the problem by adding a ToolTip control to your form and iterating over each control and adding a Tool Tip message to each control that is the name of the control.
First, add a ToolTip object to your form (from the Tools section of the designer.) You can rename it, but for the sake of my demo, I left it as the default name toolTip1.
Next, add a method similar to the one I'm posting below to the code page of your form. (I'm assuming this is for C# but the code is simple and can easily be modified for VB or C++).
public void AddNameToToolTip(Control c)
{
toolTip1.SetToolTip(c, c.Name);
foreach (Control child in c.Controls) AddNameToToolTip(child);
}
Finally, from within the Form constructor, add the following line of code after the call to InitializeComponent().
AddNameToToolTip(this);
This will add a ToolTip message to each control in your form. All you should have to do is hover your mouse over each control and the ToolTip will pop up a message after a second or two displaying the name of the underlying control.
Alternatively, you can recursively adding a MouseHover event to each control and when the event is fired, write the name of the control to the debugger. This would also work if you are already using a ToolTip control within your form.

WPF Focus In Tab Control Content When New Tab is Created

I've done a lot of searching on SO and google around this problem, but can't seem to find anything else to try.
I have a MainView (window) that contains a tab control. The tab control binds to an ObservableCollection of ChildViews (user controls). The MainView's ViewModel has a method that allows adding to the collection of ChildViews, which then creates a new tab. When a new tab is created, it becomes the active tab, and this works fine. This method on the MainView is called from another ViewModel (OtherViewModel).
What I am trying to do is set the keyboard focus to the first control on the tab (an AutoCompleteBox from WPFToolkit*) when a new tab is created. I also need to set the focus the same way, but WITHOUT creating a new tab (so set the focus on the currently active tab).
(*Note that there seem to be some focus problems with the AutoCompleteBox--even if it does have focus you need to send a MoveNext() to it to get the cursor in its window. I have worked around this already).
So here's the problem. The focusing works when I don't create a new tab, but it doesn't work when I do create a new tab. Both functions use the same method to set focus, but the create logic first calls the method that creates a new tab and sets it to active. Code that sets the focus (in the ChildView's Codebehind):
IInputElement element1 = Keyboard.Focus(autoCompleteBox);
//plus code to deal with AutoCompleteBox as noted.
In either case, the Keyboard.FocusedElement starts out as the MainView. After a create, calling Keyboard.Focus seems to do nothing (focused element is still the MainView). Calling this without creating a tab correctly sets the keyboard focus to autoCompleteBox.
Any ideas?
Update:
Bender's suggestion half-worked.
So now in both cases, the focused element is correctly the AutoCompleteBox. What I then do is MoveNext(), which sets the focus to a TextBox. I have been assuming that this Textbox is internal to the AutoCompleteBox, as the focus was correctly set on screen when this happened. Now I'm not so sure. This is still the behavior I see when this code gets hit when NOT doing a create. After a create, MoveNext() sets the focus to an element back in my MainView.
The problem must still be along the lines of Bender's answer, where the state of the controls is not the same depending on whether a new tab was created or not. Any other thoughts?
Final Update
As noted, majocha's suggestion worked.
I wanted to update this in case anyone happened upon this same problem with the AutoCompleteBox. It appears that setting focus does not activate it in the UI--you need to do a MoveNext on it to move focus forward once to the control's internal Textbox. This is based on my debugging experience, which may not be 100% scientific. If I have time, I will attempt to create a small repro project and submit it to the WPFToolkit team.
You can try defering the focus change with
Dispatcher.BeginInvoke(MyChangeFocusAction, DispatcherPriority.ContextIdle);
It will get queued after layout and properties updates are done.
I don't think it's best practice, but it works for me.
The control must be visible to be focused, you may try to defer focusing by subscribing to the IsVisibleChanged event, something similar to the following should work:
public static void setFocusLate(this Control control)
{
DependencyPropertyChangedEventHandler handler = null;
handler = delegate
{
control.Focus();
control.IsVisibleChanged -= handler;
};
control.IsVisibleChanged += handler;
}

Resources