WPF TextBox.SelectAll () doesn't work - textbox

I have used the following template in my project:
<DataTemplate
x:Key="textBoxDataTemplate">
<TextBox
Name="textBox"
ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"
Tag="{Binding}"
PreviewKeyDown="cellValueTextBoxKeyDown">
<TextBox.Text>
<MultiBinding
Converter="{StaticResource intToStringMultiConverter}">
<Binding
Path="CellValue"
Mode="TwoWay">
<Binding.ValidationRules>
<y:MatrixCellValueRule
MaxValue="200" />
</Binding.ValidationRules>
</Binding>
<Binding
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type y:MatrixGrid}}"
Path="Tag"
Mode="OneWay" />
</MultiBinding>
</TextBox.Text>
</TextBox>
</DataTemplate>
I used this template to create an editable matrix for the user. The user is able to navigate from cell to cell within the matrix and I would like to highlight the data in the selected textbox but it doesn't work. I called TextBox.Focus () and TextBox.SelectAll () to achieve the effect but nothing. The Focus () works but the text never gets highlighted.
Any help is welcome and appreciated.

Okay, if anyone is interested, the solution to this problem of mine was to include the statement e.Handled = true; in the event handler method where the textBox.SelectAll() and textBox.Focus() are called.
The problem was that I attached an event handler to the textbox's PreviewKeyDown event which handles a tunneling event and probably the SelectAll() and Focus() calls are ignored without calling the e.Handled = true; statement.
Hope it'll help someone.

Without the rest of your code it's difficult to say whether this will work for you, but I put together a small sample using your DataTemplate (minus the parts that refer to code that wasn't posted).
I was able to select all the text in the text boxes by adding a GotFocus event handler to the TextBox in the DataTemplate:
<TextBox
...
GotFocus="textBox_GotFocus"
...>
...
</TextBox>
And the code-behind:
private void textBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox textBox = sender as TextBox;
if (textBox != null)
{
textBox.SelectAll();
}
}
Let me know if you are attempting to select all under different circumstances (not when the box receives focus).

Here's a very good very simple solution (I don't know if it works for your template, but give it a try): http://social.msdn.microsoft.com/forums/en-US/wpf/thread/564b5731-af8a-49bf-b297-6d179615819f

Related

ZK Binding NotifyChange not work on onChanging Event?

I currently use ZK for web-development. Here is my case:
I implement instant search, once text change=> perform search.
Zul File
<textbox id="textSearch" sclass="search_text">
<attribute name="onChanging">
lbOnChangingSearch.setValue(event.getValue());
vm.onChangingTextSearch();
</attribute>
</textbox>
<label id="lbOnChangingSearch" visible="false"></label>
<grid id="gridChapter" model="#load(vm.chapterInPage)">
....
</grid>
Controller code
ListModelList<ChapterJoinComic> chapterInPage;
public ListModelList<ChapterJoinComic> getChapterInPage() {
return chapterInPage;
}
#NotifyChange({ "topComics", "chapterInPage"} )
#Command
public void onChangingTextSearch() {
FilterObject fo = getFilterObject();
fo.setSearch_str(lbOnChangingSearch.getValue());
//
doSearch(fo); // Change chapterInPage
// Manually post Not
BindUtils.postNotifyChange(null,null,this.chapterInPage,"chapterInPage");
}
Problem
After call onChangingText search, Grid dont update databinding.
But if I continue change text (more call onChangingTextSearch ). The Grid will update, but the updated value is the previous value.
It seems the Grid is a-step slower than my latest Model object.
Note If I use onOK instead of onChanging event, the databinding works well.
Anyone can help me. Thanks in advance!
In addition of Malte his answer.
Textbox only sends data to the server with the onChange event to avoid needless network traffic.
If you want to send data to the server with the onChanging event, you need to do :
<textbox instant="true" />
In this case the client will update almost instantly to the server (if you type fast, it will be when you stop typing)
You should remove the BindUtils.postnotifyChange when you use #NotifyChange already, and you use it wrong anyway: the third parameter should be this instead of this.chapterInPage. The JavaDoc explains that you need to specify the bean whose property is changing and the name of the property.
Furthermore, replace your onChanging attribute with the proper way to call a command:
<textbox id="textSearch" sclass="search_text"
onChanging="#command('onChangingTextSearch')" />
Consult the documentation for more information on how to use commands. I think because you do not use the command as a command, the #NotifyChange is not triggered. And your postNotifyChange is wrong, as I said.
Let me know if that works or if there are other problems remaining.
EDIT
I just re-created an example on my own, and it seems to work. Try it like this:
ViewModel --------------------------------
private String searchText = "";
#NotifyChange({"chapterInPage", "searchText"})
#Command
public void onChangingTextSearch(#BindingParam("text") String searchText)
{
this.searchText = searchText;
}
public String getSearchText()
{
return searchText;
}
public ListModelList<String> getChapterInPage()
{
return new ListModelList<>(searchText.split(""));
}
zul --------------------------------------
<textbox onChanging="#command('onChangingTextSearch', text=event.value)" />
<label id="lbl" value="#load(model.searchText)" />
<listbox model="#load(model.chapterInPage)" />
Note that I use command binding to call the search method in the model instead of calling it "manually" in an onChanging listener. This way, I actually execute it as a command, which triggers the notifyChange. When you call it like vm.onChangingTextSearch() in a listener, the #NotifyChange is ignored.
This way, it works as expected, and with every character typed (well, after a couple of millisenconds delay), the list updates. Another advantage is that you do not have to bind your label into the view model, something that zk's documentation discourages.
Can you try to link your zul and model like this and tell me if it works. If it doesn't, you might want to try to create an example on zkFiddle that re-produces your code's behavior.

How to set focus of UIComponent after <f:ajax request completed?

First of all, Thanks a lot all of you for your continuous support.
I have a problem releated .xhtml and 'f:ajax'.
I am setting richfaces:collapsiblepanel 'expanded' attribute by bean variable which is default collapsed and on blur event it gets expanded. I want to set focus a UIComponent after f:ajax request compeleted. And for that I have written a function in javascript and called it in 'onevent' of f:ajax.
But onevent function fires before panel open and I can not able to set focus on UIComponent which are define in that collapsible panel.
How can I setFocus or How can I fire that function after ajax request compeleted ?
Thanks in advance.
Your js function should look like this
function doTheFocus(data) {
if (data.status === 'success') {
//here goes the js code that will set the focus
//this code will be executed only when the ajax will be done
}
}
And here is how your f:ajax will look like
<f:ajax onevent="doTheFocus" />
If you want to call the js function of the focus when the panel is opened you can try
<rich:collapsiblePanel onswitch="doTheFocus"
or (I'm not sure...)
<rich:collapsiblePanel onswitch="doTheFocus()"
If you eventually will use the onswitch , you might be needed to add some logic inside doTheFocus function to check if the panel is expanded or not...

Ajax attached to Composite Component updates model but does not fire listener

I have a custom component location. I want that, when a change is done, the model is update so another component (an autocomplete) is to show only results related to the location value. Also, that component is rerendered to reset it.
I have a page with the following code (simplified):
<h:form id="ticketForm">
...
<loc:location id="locationId" <-- CUSTOM COMPONENT
hiddenFieldValue="#{ticketCtrl.ticket.location}"
visibleFieldValue="#{ticketCtrl.ticket.locationDescription}"
rendered="#{ticketCtrl.ticketModifiable}">
<f:ajax event="changeLocation" render=":ticketForm:gfhId" <-- AJAX CALL.
execute=":ticketForm:locationId" listener="#{ticketCtrl.locationListener}"/>
</loc:location>
...
</h:form>
When the value in the component is changed, the model is updated and :ticketForm:gfhId is rendered as needed, but the listener(which performs additional resets) is not executed.
Attaching the ajax to a simpler control results in the listener being executed; v.g.
<h:inputText id="contactId"
value="#{ticketCtrl.ticket.contactPerson}"
disabled="#{not ticketCtrl.ticketModifiable}">
<f:ajax event="change" render=":ticketForm:gfhId"
execute=":ticketForm:locationId" listener="#{ticketCtrl.locationListener}"/>
</h:inputText>
works perfectly.
I do not know if it may be related as how the changeLocation event is fired; inside my component I define it as
<composite:interface>
...
<composite:clientBehavior name="changeLocation" event="change" targets="visibleId"/>
</composite:interface>
with visibleId being a readonly text; when it is changed by javascript I fire the change event on it with JS.
function launchEvent(fieldName) {
if ("fireEvent" in fieldName) {
fieldName.fireEvent("onchange");
} else {
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
fieldName.dispatchEvent(evt);
}
}
The info I find in other questions is about making ajax an inner part of the composite component, here I want ajax detached because I probably won't need it in other uses of the component.
I am using JBoss 6.1 wih Mojarra 2.1.9 and Richfaces 4.
Thanks in advance.
UPDATE:
Even after finding jarek.jpa's answer right, if someone wants to check the code it is here:
The composite component
http://pastebin.com/9wqMVfR5
The main form
http://pastebin.com/i39ys2D9
This may have to do with the "readonly" attribute set to true. Though you manage to send the change-event by hand (JS), the server-side processing of the listener may be dropped due to the readonly state. See e.g. jsf (richfaces) readonly input text validation.

Dynamically change textbox to multiline

I am working on a Firefox extension. I have a simple single-line textbox. When a user pastes in text, I want to detect if the text has newlines and if it does, I want to expand the textbox into a multiline textbox.
I have
<textbox id="textbox" rows="5" wrap="off" newlines="pasteintact" oninput="adjustTextbox(this)" flex="1"/>
and on the JS side, I have
adjustTextbox(txtBox) {
if(!txtBox.getAttribute('multiline') && txtBox.value.match(/[\r\n]/)) {
txtBox.setAttribute('multiline', true);
}
}
The problem is that, while the textbox does get converted to a 5 row multiline textbox, the value that is pasted in is lost and the textbox is blank. Am I doing something wrong here?
Short answer: no, you aren't doing anything wrong, the value is expected to be cleared when you switch from single-line to multi-line. Long answer: the <textbox> element doesn't actually hold the value itself, it rather contains an anonymous <html:input type="text>. When you add the multiline attribute a different XBL binding applies to the element and that anonymous text field is replaced by <html:textarea>. Obviously, the value gets lost in the process.
You could try to save the value and to restore it after you add the multiline attribute. The problem is that it is hard to tell when the binding actually applies, there is a delay that is not really predictable. So the better solution would be to have both a single-line and a multi-line text box in your document and make sure that one of them is always collapsed:
<textbox id="textbox" newlines="pasteintact" oninput="adjustTextbox(this)" flex="1"/>
<textbox id="textbox2" collapsed="true" multiline="true" rows="5" wrap="off" flex="1"/>
And on the JavaScript side:
function adjustTextbox(txtBox) {
if(!txtBox.getAttribute('multiline') && txtBox.value.match(/[\r\n]/)) {
var txtBox2 = document.getElementById("textbox2");
txtBox2.value = txtBox.value;
txtBox.collapsed = true;
txtBox2.collapsed = false;
}
}

Silverlight event handling

I try to catch the MouseUp event from the slider but it never goes inside of the handler. The code is usual:
<Slider x:Name="sliderTime"
MouseLeftButtonDown="sliderTime_MouseLeftButtonDown"
MouseLeftButtonUp="sliderTime_MouseLeftButtonUp" />
And in code behind:
private void sliderTime_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//some code
}
Is it bug of the slider or something else?
Thanks
I duplicated the code you posted and it worked for me.
Any chance the event isn't actually wired up?
I built it two different ways and the event fired for me. How did you build it?
Also check to see if you somehow have an object covering the slider?
Version 1:
Open Blend 3, file>create project, Silverlight 3 Application + Website. Added a slider and named it (simply because you did). Added a label (to check the event firing).
Selected the component, switched over events and double-clicked the events for MouseLeftButtonDown and MouseLeftButtonUp to create the events and code-behind stubs. Updated the label when MouseLeftButtonUp fires.
Version 2: Open Blend 3, file>create project, Silverlight 3 Application + Website. Added a slider and a label. Right-clicked on the silverlight project in Blend and opened it in VS2008. Wired up the events in markup using intellisense.
Both version worked for me. Is this part of other code? If so try to make a version with just the slider and see if that works, if it does then something in your existing code may be off. I'll post my code so you can see it.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dataInput="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input"
x:Class="SilverlightAppSlider2Test.MainPage"
Width="640" Height="480">
<Grid x:Name="LayoutRoot" Background="White">
<Slider x:Name="sliderTime" MouseLeftButtonUp="Slider_MouseLeftButtonUp" MouseLeftButtonDown="sliderTime_MouseLeftButtonDown" Width="Auto" Height="20" Margin="5"/>
<dataInput:Label x:Name="Label1" Width="200"/>
</Grid>
</UserControl>
AND
private void Slider_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
// TODO: Add event handler implementation here.
Label1.Content = "Mouse button left released.";
}
Since Silverlight 2 Beta 2, many controls dont fire the MouseDown/MouseUp events, and I believe that Slider is one of them. You can "work around" that by inheriting from Slider and writing custom code to fire these events.
Take a look here: http://forums.silverlight.net/forums/p/18328/61917.aspx
You can use the FrameworkElement.AddHandler method to handle this event. You won't be able to wire it up in xaml however. More info in this blog post:
http://blogs.msdn.com/kmahone/archive/2009/03/19/handling-mouse-input-events-on-controls.aspx

Resources