How to internationalize a converter or renderer in Wicket? - localization

I'm translating a web application and things are generally going smoothly with wicket:message and properties files. But Wicket always wants to have a component for looking up strings.
How can I translate converters and renderers (i.e. implementations of IConverter and IChoiceRenderer) which don't have access to any Wicket component in their methods?
So far I found one way - Application.get().getResourceSettings().getLocalizer().getString(key, null) - but I have to make the strings "global", i.e. associated with the application class. That's not nice for separation and reuse. How can I do it better?

I think you should invent you own way how to achieve this. Here in my current project we registered our own IStringResourceLoader like this:
IStringResourceLoader stringResourceLoader = new OurOwnResourceLoaderImpl();
Application.get().getResourceSettings().getStringResourceLoaders().add(stringResourceLoader);
Then for example in IChoiceRenderer we just call Application.get().getLocalizer().getString("key", null).
Inside our IStringResourceLoader we are looking for bundles (property files) with some string pattern according our own conventions.
Or you can just register localization bundle (ie. properties file) distributed inside your library's jar in Application#init through org.apache.wicket.resource.loader.BundleStringResourceLoader.
Afaik there is no standard way to do that so it's up to you what path you choose.
Updated:
I found another solution how your library/extension can register it's own localization by itself so you needn't to touch Application#init or create your own IStringResourceLoaders.
There is preregistered string resource loader org.apache.wicket.resource.loader.InitializerStringResourceLoader (see wickets default IResourceSetting implementation ie. ResourceSetting and it's constructor) which uses wicket's Initializer mechanism - see IInitializer javadoc - basically you add wicket.properties file in your jar class root (ie. it is in default/none package) and inside file there is:
initializer=i.am.robot.MyInitilizer
then i.am.robot.MyInitilizer:
public class MyInitializer implements IInitializer {
/**
* #param application
* The application loading the component
*/
void init(Application application) {
// do whatever want
}
/**
* #param application
* The application loading the component
*/
void destroy(Application application) {
}
}
and now you create your localization bundles in same package and same name as IInitializer implementation (in our example MyInitializer)

I think I found another way...
I noticed that IStringResourceLoader also has a method String loadStringResource(Class<?> clazz, String key, Locale locale, String style); (and one more parameter for variation in newer Wicket versions) which does not require a component. clazz is supposed to be a component class, but... it doesn't actually have to be :)
I was able to implement my own class MyLocalizer extends Localizer with a new method
getString(String key, Class<?> cl, IModel<?> model, Locale locale, String defaultValue)
which works in a similar way to
getString(String key, Component component, IModel<?> model, String defaultValue)
but uses the class directly instead of a component. It still uses the same properties cache and resource loaders.
Then I wrote an abstract class MyConverter implements IConverter which has a MyLocalizer getLocalizer() and a few getString methods like the Component class. Basically it does getLocalizer().getString(key, getClass(), model, locale, defaultValue), so the properties can now be attached to the converter class.
Seems to work :)

If I understand your question...
You can use package based properties that means if you put your keys/values into a property file 'package.properties' in a package. Each localized resource of any subpackage under that package returns the value associated to the requested key until you override it in another property file.
The file name is 'package.properties' in Wicket prior to 1.6.x and 'wicket-package.properties' in Wicket 1.6+
See
https://cwiki.apache.org/confluence/display/WICKET/Migration+to+Wicket+6.0#MigrationtoWicket6.0-package.propertiesrenamedtowicket-package.properties
However it works just for componet, outside the componet (when component argument is null), it is possible to use:
WicketApplication.properties (the WebApplication class is WicketApplication.class, this property file is in the same package).
applicationGlobalProperty=My Global Localized Property
wicket-package.properties (package based, place it in the same package as the page)
localText=Localized text: A local component text based on wicket-package.properties
LocalizedPage.html (markup template)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Localized Page</title>
</head>
<body xmlns:wicket="http://wicket.apache.org">
<div>
<div>
<h2>Texts</h2>
<div>
<wicket:message key="localText"/> <br/>
<span wicket:id="localizedLabel"></span>
</div>
</div>
</div>
</body>
</html>
LocalizePage.java (code)
public class LocalizedPage extends WebPage {
private static final long serialVersionUID = 1L;
public LocalizedPage() {
super();
}
#Override
protected void onInitialize() {
super.onInitialize();
add(new Label("localizedLabel", new AbstractReadOnlyModel<String>() {
private static final long serialVersionUID = 1L;
#Override
public String getObject() {
return WicketApplication.get().getResourceSettings().getLocalizer().getString("applicationGlobalProperty", null);
}
}));
}
}
See the full example on https://repo.twinstone.org/projects/WISTF/repos/wicket-examples-6.x/browse

Related

Rejecting published file request for file that has not been published. Tried all the options but didn't work

I am trying to implement a sample application where all the javascript (JS) & CSS files use many png files.
I referred many articles but they could not help me.
For all the png files, I get the following error,
Sample error part,
Jan 29, 2019 3:25:22 PM com.vaadin.server.communication.PublishedFileHandler handleRequest
WARNING: Rejecting published file request for file that has not been published: css/images/chartIcon.png
Jan 29, 2019 3:25:22 PM com.vaadin.server.communication.PublishedFileHandler handleRequest
WARNING: Rejecting published file request for file that has not been published: css/images/sunburst.png
Jan 29, 2019 3:25:22 PM com.vaadin.server.communication.PublishedFileHandler handleRequest
WARNING: Rejecting published file request for file that has not been published: css/images/treemap.png
Jan 29, 2019 3:25:40 PM com.vaadin.server.communication.PublishedFileHandler handleRequest
WARNING: Rejecting published file request for file that has not been published: css/images/sprite.png
The following is the folder structure that I have,
de.qsoft.manatee.web.vaadin.myapp
de.qsoft.manatee.web.vaadin.myapp.css --> Contains all CSS files
de.qsoft.manatee.web.vaadin.myapp.fileMenu --> Contains all CSS files
de.qsoft.manatee.web.vaadin.myapp.widgets --> Contains all CSS files
de.qsoft.manatee.web.vaadin.myapp.scripts --> contains all js files
de.qsoft.manatee.web.vaadin.myapp.widgets --> contains all js files
de.qsoft.manatee.web.vaadin.myapp.colorpicker --> contains all js files
SpreadJSWidget.Java
#JavaScript({
"scripts/jquery-1.11.1.min.js",
"scripts/jquery-ui-1.10.3.custom.min.js",
"spreadjs_connector.js",
"colorpicker/colorPicker.js",
"fileMenu/fileMenu.js",
"scripts/actionmanager.js",
"scripts/app.js",
"scripts/bootstrap.min.js",
"scripts/FileSaver.min.js",
"scripts/gc.spread.excelio.12.0.5.min.js",
"scripts/gc.spread.sheets.all.12.0.5.min.js",
"scripts/gc.spread.sheets.barcode.12.0.5.min.js",
"scripts/gc.spread.sheets.charts.12.0.5.min.js",
"scripts/gc.spread.sheets.pdf.12.0.5.min.js",
"scripts/gc.spread.sheets.print.12.0.5.min.js",
"scripts/gc.spread.sheets.shapes.12.0.5.min.js",
"scripts/license.js",
"scripts/resources.js",
"scripts/ribbon-data.js",
"scripts/ribbon.js",
"scripts/sample.js",
"scripts/spreadActions.js",
"scripts/util.js",
"widgets/addChartElement/chartAddChartElement.js",
"widgets/chartColorPicker/chart-colorPicker.js",
"widgets/chartLayoutPicker/chartLayoutPicker.js",
"widgets/richText/richTextEditor.js"
})
#StyleSheet({
"colorpicker/colorPicker.css",
"css/font-awesome/css/font-awesome.min.css",
"css/bootstrap-theme.min.css",
"css/bootstrap.min.css",
"css/borderpicker.css",
"css/colorpicker.css",
"css/excel2013.css",
"css/gc.spread.sheets.12.0.5.css",
"css/gc.spread.sheets.excel2013white.12.0.5.css",
"css/insp-slicer-format.css",
"css/insp-table-format.css",
"css/inspector.css",
"css/sample.css",
"css/shapes.css",
"fileMenu/fileMenu.css",
"widgets/addChartElement/chartAddChartElement.css",
"widgets/chartColorPicker/chart-colorPicker.css",
"widgets/chartLayoutPicker/chartLayoutPicker.css",
"widgets/richText/richTextWithRichEditor.css",
})
public class SpreadJSWidget extends AbstractJavaScriptExtension
{
/**
*
*/
private static final long serialVersionUID = -804316208810859887L;
public interface ValueChangeListener extends Serializable {
void valueChange();
}
ArrayList<ValueChangeListener> listeners = new ArrayList<ValueChangeListener>();
public void addValueChangeListener(ValueChangeListener listener) {
listeners.add(listener);
}
/**
*
*/
public SpreadJSWidget() {
// TODO hari: Auto-generated constructor stub
}
/*'***************************************************************************************
* Static/Inner class members
******************************************************************************************/
/*'***************************************************************************************
* Class members
******************************************************************************************/
public void setValue(String value) {
getState().value = value;
}
#Override
protected void extend(AbstractClientConnector target) {
// TODO hari: Not Yet Implemented
super.extend(target);
}
public String getValue() {
return getState().value;
}
#Override protected SpreadJSWidgetState getState() {
return (SpreadJSWidgetState) super.getState();
}
}
I tried the following step by step but i could not get expected results,
I have kept all the png files under the directory "de.qsoft.manatee.web.vaadin.myapp.css" as "de.qsoft.manatee.web.vaadin.myapp.css.images"
Under VAADIN folder, i copied all the png files as "VAADIN/css/images/"
Under VAADIN folder like "VAADIN/themes/mytheme/img/css/images"
Under VAADIN folder like "VAADIN/themes/mytheme/layouts/css/images"
#Theme("mytheme")
public class MyUI extends UI {
#Override
protected void init(VaadinRequest vaadinRequest) {
SpreadWidget widget = new SpreadWidget();
setContent(widget);
}
#WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
#VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
public static class MyUIServlet extends VaadinServlet {
}
}
Please let me know where should i put all png files. Each css is refering image file as
http://localhost:8080/spreadjs/APP/PUBLISHED/css/images/AllShapes.png
What happens here is caused by a security feature. Since the files are in this case served directly from the classpath, Vaadin takes some precautions to prevent accidentally also publishing other things from the classpath, e.g. something like DatabaseConnection.java which might contain sensitive passwords.
For this reason, only files that are explicitly published using a #StyleSheet, #JavaScript or #HtmlImport annotation are available. Since there is no corresponding annotation for e.g. css/images/AllShapes.png, the server ignores those requests.
I'm aware of a couple of potential workarounds in this kind of case, but neither is really elegant:
Put the images in e.g. VAADIN/css/images and update the CSS to use an appropriate number of ../ segments to cancel out the /APP/PUBLISHED/ part of the URL. The URL in the CSS would thus be something along the lines of ../../VAADIN/css/images.AllShapes.png.
Put the CSS along with the images in VAADIN/. In that way, you don't need to change the URLs that refer to the images, but you instead need to manually load the CSS instead of relying on the convenient #StyleSheet annotation. In that case, I'd recommend using something like ui.getPage().getStyles().add(new ThemeResource("../../css/name.css"));. The ../../ part is to cancel out themes/mytheme/ that will automatically be used for a theme resource. You could do this in e.g. the attach() method (just remember to also call super.attach()). You should preferably also add some logic that only adds the dependency if it hasn't already been done previously for the same UI instance.
Use the internal LegacyCommunicationManager.registerDependency method to also register your images to be available directly from the classpath. You can find an instance to LegacyCommunicationManager using vaadinSession.getCommunicationManager().
As an unrelated note, I'd recommend combining the different scripts and CSS files into a single file of each type. The reason for this is that loading lots of small files over HTTP causes some performance overhead that can be avoided by bundling the files together.

HTML Extensions for wrapping other extensions

Most times when using DevEx MVC extensions, I find myself having to use repetitive code to generate the controls/layouts that I use on a regular basis. For example, I tend to prefer left-aligned captions to controls. Ideally, I'd be able to do something like this and have it "just work":
#Html.DevExpress().TextBoxFor(m => m.Notes).GetHtml()
However, in order to place the caption on the left, I need to also pass in a settings object for it, or dome something much more verbose such as:
#Html.DevExpress().TextBox(
s => {
// ...
s.Properties.CaptionCellStyle.Width = 100;
// ...
}
).Bind(Model.Notes).GetHtml()
What I thought to do was create my own set of extensions that would wrap the DevEx extensions, giving me some sort of common/core customization layer, so I could do something like this:
#Html.MyComponents().TextBoxFor(m => m.Notes)
This call would in turn call the DevExpress TextBoxExtension with a common set of settings and output the DevEx textbox as desired.
I've worked this up via custom html extensions (code below), but have two issues with this basic implementation:
The control renders at the very top of the Body element, not at the position in which it's placed in the view, and
There's a JavaScript error "ASPxClientTextBox" is not defined (this is part of the client-side scripting that DevEx uses with their controls).
I was hoping this would be an easy "wrap it and go" type of scenario. Is there some basic concept of these custom HTML extensions that I'm missing? Or does anyone know if this is a general limitation in trying to wrap another company's pre-existing extensions?
Here's the code I have implemented (which is not yet fully fleshed out, just trying for proof of concept here):
public static class HtmlHelpers
{
public static MyComponentsHtmlHelpers<TModel> MyComponents<TModel>(this HtmlHelper<TModel> html) {
return new MyComponentsHtmlHelpers<TModel>(html);
}
}
public class MyComponentsHtmlHelpers<TModel>
{
private HtmlHelper<TModel> html;
public MyComponentsHtmlHelpers(HtmlHelper<TModel> html) {
this.html = html;
}
public MvcHtmlString TextBoxFor<TValue>(Expression<Func<TModel, TValue>> expression) {
var data = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
string propertyName = data.PropertyName;
System.Diagnostics.Debug.WriteLine("PROPERTY NAME: " + propertyName);
TextBoxSettings s = new TextBoxSettings();
s.Name = "textbox_" + propertyName;
s.Properties.Caption = propertyName;
s.Properties.CaptionCellStyle.Width = 100;
TextBoxExtension tb = new TextBoxExtension(s);
return tb.GetHtml();
}
}
Nevermind - cleaning the solution and rebuilding as well as force refreshing the test browser a few times and ensure there's no cache and... now everything works as intended.
(not sure if I ought to delete this question or leave it around in case someone wants to attempt the same... I'll leave it for now, feel free to remove)

Wicket and Reusable Link

'm trying to create a reusable link class that extends Link. I have a webpage with about 7 menu items and I'm using inheritance for my application. I want to create a reusable link class to shorten the length of my code..
As of now the link creates and runs fine when I add(new Link....) as an anonymous class inside oninitialize().
The custom link class (which is an inner class of the base page) works fine when I hard code the instance of the new page to go to, and assign it to a "Page" reference, then pass it into setResponsePage();
The problem is, I'm passing trying to be able to pass object through the constructor generically. When I pass it through the constructor, and try to travel to the new page, I get a session has expired.
I've tried using generics for the class, and I've also tried just declaring a Page reference as a parameter value. Am I supposed to use some sort of Model? Or can someone provide an example of how to do this? I want to be able to use this custom link class to add new links for the 7 menu items, which each have there own class...
Code that works:
add(new Link("userPageLink")
{
public void onClick()
{
pageTitle = "User";
Page next = new UserPage();
setResponsePage(next);
}
});
Modified code that gives page expired upon click:
public class CustomLinkToNewPage extends Link
{
private String title;
private Page next;
public CustomLinkToNewPage(String id, String title, Page newPage)
{
super(id);
next = newPage;
this.title = title;
}
#Override
public void onClick()
{
SSAPage.pageTitle = title;
setResponsePage(next);
}
}
This might be due to the fact that in the first version you crate the Page object when the onClick method of the Link object is called and in the second version, the Page object is created on Page-construction (way earlier).
You might get the result if you pass the Pageclass of the responsepage instead on an instance.
Component features setters for these either with
public final <C extends IRequestablePage> void setResponsePage(java.lang.Class<C> cls, PageParameters parameters)
or without parameters.
public final <C extends IRequestablePage> void setResponsePage(java.lang.Class<C> cls)
See Javadoc for more information.
I ended up doing:
public class CustomLinkToNewPage<T extends SSAPage> extends Link
SSAPage is my base page that extends WebPage... So any object passed in to this class's constructor must extend SSAPage as well.
public CustomLinkToNewPage(String id, Class<T> name)
Then I passed in the .class reference to the object, and created a new instance of the object using reflection.. then set that instance to Page, and passed it to setResponsePage in my onClick. Worked nicely, as I couldn't figure out how to do Nicktar's way. So this an alternative in case anyone else runs into this issue.

Modifying JSF Component Tree in PhaseListener

I'm having an issue.
I've implemented a PhaseListener, which is meant to add a style class to any UIInput components in the tree that have messages attached to them, and removes the style class if it doesn't have any messages attached to them.
The PhaseListener runs in the RENDER_RESPONSE phase, and does it's work in both the beforePhase and afterPhase methods while debugging. While debugging, I found that beforePhase doesn't have access to the full component tree, but afterPhase does. Any changes done in afterPhase aren't rendered though.
How do I go about this? I want this to be completely server side.
Thanks,
James
The JSF component tree is only available after the view build time. The RENDER_RESPONSE phase is not necessarily a good moment to have access to the full JSF component tree before it gets rendered. During an initial GET request without any <f:viewAction>, the full component tree is only available in the afterPhase as it's being built during the RENDER_RESPONSE. During a postback the full component tree is available in the beforePhase, however, when a navigation to a different view has taken place, then it would stil be changed during the RENDER_RESPONSE phase, so any modifications would get lost.
To learn what exactly the view build time is, head to the question What's the view build time?
You basically want to hook on "view render time" rather than beforePhase of RENDER_RESPONSE phase. JSF offers several ways to hook on it:
In some master template, attach a preRenderView listener to <f:view>.
<f:view ...>
<f:event type="preRenderView" listener="#{bean.onPreRenderView}" />
...
</f:view>
public void onPreRenderView(ComponentSystemEvent event) {
UIViewRoot view = (UIViewRoot) event.getSource();
// The view is the component tree. Just modify it here accordingly.
// ...
}
Or, implement a global SystemEventListener for PreRenderViewEvent.
public class YourPreRenderViewListener implements SystemEventListener {
#Override
public boolean isListenerForSource(Object source) {
return source instanceof UIViewRoot;
}
#Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
UIViewRoot view = (UIViewRoot) event.getSource();
// The view is the component tree. Just modify it here accordingly.
// ...
}
}
To get it to run, register it as below in faces-config.xml:
<application>
<system-event-listener>
<system-event-listener-class>com.example.YourPreRenderViewListener</system-event-listener-class>
<system-event-class>javax.faces.event.PreRenderViewEvent</system-event-class>
</system-event-listener>
</application>
Or, provide a custom ViewHandler wherein you do the job in renderView().
public class YourViewHandler extends ViewHandlerWrapper {
private ViewHandler wrapped;
public YourViewHandler(ViewHandler wrapped) {
this.wrapped = wrapped;
}
#Override
public void renderView(FacesContext context, UIViewRoot view) {
// The view is the component tree. Just modify it here accordingly.
// ...
// Finally call super so JSF can do the rendering job.
super.renderView(context, view);
}
#Override
public ViewHandler getWrapped() {
return wrapped;
}
}
To get it to run, register as below in faces-config.xml:
<application>
<view-handler>com.example.YourViewHandler</view-handler>
</application>
Or, hook on ViewDeclarationLanguage#renderView(), but this is a bit on the edge as it isn't really intented to manipulate the component tree, but to manipulate how to render the view.
Unrelated to the concrete problem, this all is not the right solution for the concrete functional requirement as stated in your question:
which is meant to add a style class to any UIInput components in the tree that have messages attached to them, and removes the style class if it doesn't have any messages attached to them
You'd really better head for a client side solution rather than manipulating the component tree (which would end up in JSF component state!). Imagine the case of inputs in iterating components such as <ui:repeat><h:inputText>. There's physically only one input component in the tree, not multiple! Manipulating the style class via UIInput#setStyleClass() would get presented in every iteration round.
You'd best visit the component tree using UIViewRoot#visitTree() as below and collect all client IDs of invalid input components (this visitTree() approach will transparently take iterating components into account):
Set<String> invalidInputClientIds = new HashSet<>();
view.visitTree(VisitContext.createVisitContext(context, null, EnumSet.of(VisitHint.SKIP_UNRENDERED)), new VisitCallback() {
#Override
public VisitResult visit(VisitContext context, UIComponent component) {
if (component instanceof UIInput) {
UIInput input = (UIInput) component;
if (!input.isValid()) {
invalidInputClientIds.add(input.getClientId(context.getFacesContext()));
}
}
return VisitResult.ACCEPT;
}
});
And then thereafter pass invalidInputClientIds in flavor of a JSON array to JavaScript which will then grab them via document.getElementById() and alter the className attribute.
for (var i = 0; i < invalidInputClientIds.length; i++) {
var invalidInput = document.getElementById(invalidInputClientIds[i]);
invalidInput.className += ' error';
}
The JSF utility library OmniFaces has a <o:highlight> component which does exactly this.
Implemented using a ViewHandler, however it's not efficient. PhaseListener in Render Response phase doesn't have access to the component tree.

Silverlight DataGridColumn AttachedProperties

I am attempting to create an AttachedProperty for a DataGridColumn within Silverlight 3.0 and I am having some issues.
Here is the AttachedProperty:
public class DataGridColumnHelper
{
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.RegisterAttached("Header", typeof(string), typeof(DataGridColumnHelper),
new PropertyMetadata(OnHeaderPropertyChanged));
private static void OnHeaderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
string header = GetHeader(d);
var dataGridColumn = d as DataGridColumn;
if (dataGridColumn == null)
{
return;
}
dataGridColumn.Header = GetHeader(dataGridColumn);
}
public static string GetHeader(DependencyObject obj)
{
return (string)obj.GetValue(HeaderProperty);
}
public static void SetHeader(DependencyObject obj, string value)
{
obj.SetValue(HeaderProperty, value);
}
}
As you can see it is really simple, I am trying to overcome the limitation that the Header Property in the DataGridColumn class cannot be bound.
This XAML works as expected...
<Controls:DataGridTextColumn Binding="{Binding OwnerName}"
HeaderStyle="{StaticResource DataGridColumnHeaderStyle}"
Behaviors:DataGridColumnHelper.Header="User Name"/>
However this XAML throws an error...(Specifically: {System.Windows.Markup.XamlParseException: AG_E_PARSER_PROPERTY_NOT_FOUND [Line: 224 Position: 112]
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
....})
<Controls:DataGridTextColumn Binding="{Binding OwnerName}"
HeaderStyle="{StaticResource DataGridColumnHeaderStyle}"
Behaviors:DataGridColumnHelper.Header="{Binding Resources.UserNameListViewHeading, Source={StaticResource Labels}}"/>
Just for experimentation I attached this property (with the binding syntax above) to a DataGrid and checked the DataGridColumnHelper.Header property in the OnHeaderPropertyChanged method and the value was correct (and an exception wasn't thrown)
It is my understanding that the object that the AttachedProperty is attached to must be a DependencyProperty. Looking through Reflector, DataGridColumn (from which DataGridTextColumn derives) derives from DependencyProperty.
Can somebody please shed some light on this? I am trying to Localize our application, and I am having trouble with the DataGrid. I am sure I can do this in code-behind, but I am trying to avoid that.
Chris, the problem is very simple, this won't work because the DataGridTextColumn is "detached" from the Visual Tree. Your DataGridTextColumn object is rooted in the Columns collection of the DataGrid - see the indirection. So even attached properties will not work as you expect. Now there is a way to make all this work using something I'm calling Attached Bindings, see:
http://www.orktane.com/Blog/post/2009/09/29/Introducing-nRouteToolkit-for-Silverlight-(Part-I).aspx
Just remember to attach the binding properties using something that is in the VisualTree (so the Grid holding the column would do just fine.)
Hope this helps.
Try using this, im assuming UserName is a property in your viewmodel
<Controls:DataGridTextColumn Binding="{Binding OwnerName}"
HeaderStyle="{StaticResource DataGridColumnHeaderStyle}"
Behaviors:DataGridColumnHelper.Header="{Binding UserName}"/>
I cant test your scenario so my post is just an idea. Might work, might not.

Resources