I am working on android app for Honeywell EDA51 (barcode scanner).
On certain pages in entry field I want to make it work for both scanning with EDA51 and manual typing (character by character)
When I tried using Completed() event, I get good functionality for manual typing but while scanning it has problem because it always request from user to manually complete input (press ✓)
Then I implemented it using TextChanged() event where I ignore (just concatenate) input until it reach certain length.
private void ProductBarcodeEntry_TextChanged(object sender, TextChangedEventArgs e)
{
var entry = (Entry)sender;
entry.TextChanged -= ProductBarcodeEntry_TextChanged;
try
{
var context = (DescriptionViewModel)this.BindingContext;
if (context.controlValue%4 == 0)
{
context.controlValue = 1;
context.Barcode = context.BarcodeProduct;
bool p = context.ExecuteScanCommand().Result;
if (!p)
{
this.ProductBarcodeEntry.Text = context.Barcode;
this.ProductBarcodeEntry.CursorPosition = context.Barcode.Length;
}
else
{
this.BoxBarcodeEntry.Text = context.BoxID;
this.ProductBarcodeEntry.Text = "";
this.ProductBarcodeEntry.Focus();
}
}
else
{
}
context.controlValue++;
}
catch (Exception ex)
{
}
finally
{
entry.TextChanged += ProductBarcodeEntry_TextChanged;
}
Those control values are something I tried to catch how much times does it triggers event. At first I thought it fires when ever in this code I manipulate with this.ProductBarcodeEntry.Text but when I follow execution in debugger it doesn't recall event when it reach that point, it goes normal to the final segment and after that it starts again. I got about 4 calls but to be honest at some point both device and debugger just doesn't respond, somewhere inside code when it is stopped on some breakpoint after step over it just ignore rest of breakpoints, and device after some times do what it was supposed.
private void BoxBarcodeEntry_TextChanged(object sender, TextChangedEventArgs e)
{
var entry = (Entry)sender;
entry.TextChanged -= BoxBarcodeEntry_TextChanged;
try
{
var context = (DescriptionViewModel)this.BindingContext;
if (context.controlValue == 0)
{
context.controlValue = 1;
context.Barcode = context.BarcodeBox;
bool p = context.ExecuteScanCommand().Result;
//bool p = context.ScanCommand.Execute(this);
if (!p)
{
this.BoxBarcodeEntry.Text = context.Barcode;
this.BoxBarcodeEntry.CursorPosition = context.Barcode.Length;
}
else
{
this.BoxBarcodeEntry.Text = context.BoxID;
this.ProductBarcodeEntry.Text = "";
this.ProductBarcodeEntry.Focus();
}
}
else
{
}
}
catch (Exception ex)
{
}
finally
{
entry.TextChanged += BoxBarcodeEntry_TextChanged;
}
}
And XAML part
<Entry Grid.Row="2" TextChanged="BoxBarcodeEntry_TextChanged" HorizontalOptions="CenterAndExpand" x:Name="BoxBarcodeEntry" Placeholder="Scan box barcode" Text="{Binding input.BarcodeBox, Mode=TwoWay}" TextColor="#2A5B90" WidthRequest="300"/>
<Entry Grid.Row="1" TextChanged="ProductBarcodeEntry_TextChanged" HorizontalOptions="CenterAndExpand" x:Name="ProductBarcodeEntry" Placeholder="Scan product barcode" Text="{Binding input.BarcodeProduct, Mode=TwoWay}" TextColor="#2A5B90" WidthRequest="300"/>
BoxBarcodeEntry_TextChanged() is not done, its not frequently used as product and it was useless to do same thing when product scan doesn't work well
(Just for reference it never goes to this method even when BoxBarcodeEntry.Text is changed from ProductBarcodeEntry_TextChanged()).
Functionality that I want to achieve is to have two entry fields on page, focus will be on product box because some of product doesn't have box attached to it, but anyway when user scan barcode it validates (if description is about product with box, then if it is box code it stores value in BoxBarcodeEntry, and save it in memory, then after that until next BoxBarcode is scanned it makes pairs (Box,Products) etc).
Description of products with box example: (shorts bb - BoxBarcode, pb - ProductBarcode )
Scans:
pb1 - ignores it (bb in memory is null), and clear text field
bb1 - store in memory and fills BoxBarcodeEntry.Text
bb2 - store (replace old) in memory and fills BoxBarcodeEntry.Text
pb2 - pairs with bb from memory -> (bb2,pb2) is stored somewhere in DB
pb3 - pairs with bb from memory -> (bb2,pb3) is stored somewhere in DB
...
And example of description for products without box
pb1 - (null,pb1) is stored in DB
bb1 - ignored
bb2 - ignored
pb2 - (null,pb2) is stored in DB
pb3 - (null,pb3) is stored in DB
...
Maybe I wrote too much information but main question remains same, why does it triggers those events multiple times and how to prevent (or control) that behavior.
Related
I'm trying to capture the item clicked on in a listview. Everything I've seen here deals with Xamarin Forms, I am NOT using Xamarin Forms. I build my listview and display it fine, but I cannot figure out how to capture the item click. My build code:
ListView PhoneNumberList;
PhoneNumberList = FindViewById<ListView>(Resource.Id.listViewNumbers);
ListOfPhoneNumbers = new List<string>();
if (PhoneNumberData.Tables[0].Rows.Count > 0)
{
foreach (DataRow MyDataRow in PhoneNumberData.Tables[0].Rows)
{
ListOfPhoneNumbers.Add(MyDataRow["FirstName"].ToString() + " " + MyDataRow["LastName"].ToString() + " " + MyDataRow["PhoneNumber"].ToString());
}
}
else
{
ListOfPhoneNumbers.Add("Currently there are no phone numbers available in this list
}
ArrayAdapter adapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItemMultipleChoice, ListOfPhoneNumbers);
PhoneNumberList.Adapter = adapter;
This code displays the name and phone number as intended, but I cannot figure out how to detect when the Listview is clicked. I tried:
PhoneNumberList.ItemSelected += (sender, args) =>
{
var Sel = PhoneNumberList.SelectedItem;
};
But it never gets called on the click. I've also tried:
PhoneNumberList.ItemSelected += delegate (object sender, AdapterView.ItemSelectedEventArgs args) { PhoneNumberList_ItemSelected(); };
PhoneNumberList_ItemSelected never gets called either.
My Listview XML:
<ListView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="148.4dp"
android:id="#+id/listViewNumbers" />
So what am I doing wrong?
Ok, after slogging around the internet for a few hours, I was able to work it out. It was rather simple and I had already discovered the answer, I just formated one statement wrong and it sent me on a wild goose chase to find the answer. My updated code:
ListView PhoneNumberList;
PhoneNumberList = FindViewById<ListView>(Resource.Id.listViewNumbers);
ListOfPhoneNumbers = new List<string>();
if (PhoneNumberData.Tables[0].Rows.Count > 0)
{
foreach (DataRow MyDataRow in PhoneNumberData.Tables[0].Rows)
{
ListOfPhoneNumbers.Add(MyDataRow["FirstName"].ToString() + " " + MyDataRow["LastName"].ToString() + " " + MyDataRow["PhoneNumber"].ToString());
}
}
else
{
ListOfPhoneNumbers.Add("Currently there are no phone numbers available in this list
}
ArrayAdapter adapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItemMultipleChoice, ListOfPhoneNumbers);
PhoneNumberList.Adapter = adapter;
Exactly the same, now I add the one line of code I just couldn't get right (duh):
PhoneNumberList.ItemClick += PhoneNumberList_ItemClick;
Originally I had used PhoneNumberList.ItemClick += PhoneNumberList_ItemClick(); and the error it generated sent me off on that aforementioned wild goose chase and there went several hours of my life I'll never get back, lol. The PhoneNumberList_ItemClick code:
void PhoneNumberList_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
// We now can write code here to set the checkbox in the listview to checked
// All I got to do now is figure out how to do THAT. Stay tuned ....
}
So, hopefully this will save someone the ordeal I put myself through.
**** Update ****
Didn't take long to figure out how to set the item clicked's checkbok, changes to PhoneNumberList_ItemClick code below:
void PhoneNumberList_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
ListView MyListView = (ListView)sender;
if (MyListView.IsItemChecked(e.Position))
{
MyListView.SetItemChecked(e.Position, true);
}
else
{
MyListView.SetItemChecked(e.Position, false);
}
}
.... And that's all folks ....
While I'm using frame in Mainwindow , initially i hide an item in Mainwindows.
When i pressed a button in frame Page1 , I want to make item in mainwindow as visible.But i can't do it.I tried to updatelayout() , refresh() functions but anything is changed.Anyone has a knowledge about this??
This code is in MainWindow
private void Window_Loaded(object sender, RoutedEventArgs e)
{
müsteributton.IsEnabled = false;
string yer = "Pages/kullanicigiris.xaml";
frame1.Source = new Uri(yer, UriKind.Relative);
frame1.Margin = new Thickness(-175, 0, 0, 0);
}
This code is in kullanicigiris page
private void Dispatcher_Tick(object sender, EventArgs e)
{
i++;
if (i == 2)
{
dispatcher.Stop();
frm1 = new MainWindow();
frm1.frame1 = null;
DependencyObject currParent = VisualTreeHelper.GetParent(this);
while (currParent != null && frm1.frame1 == null)
{
frm1.frame1 = currParent as Frame;
currParent = VisualTreeHelper.GetParent(currParent);
}
// Change the page of the frame.
if (frm1.frame1 != null)
{
frm1.frame1.Source = new Uri("Window1.xaml", UriKind.Relative);
frm1.müsteributton.IsEnabled = true;
}
}
}
Thanks.
You can define a DependencyProperty in the MainWindows.
<TextBlock x:Name="textBlock" Height="399" TextWrapping="Wrap" Text="Show/ Hide" VerticalAlignment="Top" Visibility="{Binding SetVisibility, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
public static readonly DependencyProperty SetVisibilityProperty =
DependencyProperty.Register("SetVisibility", typeof(Visibility), typeof(Mainfreampage), new
PropertyMetadata(Visibility.Visible, null));
public Visibility SetVisibility
{
get { return (Visibility)GetValue(SetVisibilityProperty); }
set { SetValue(SetVisibilityProperty, value); }
}
In your page click event, you can use the following code find the MainWindows and change the DependencyProperty value.
var mw = Application.Current.Windows
.Cast<Mainfreampage>()
.FirstOrDefault(window => window is Mainfreampage) as Mainfreampage;
mw.SetVisibility = Visibility.Hidden;
Your bug is here:
frm1 = new MainWindow();
You are creating a brand new window, and then making your changes in that window.
But: that's not the window the user's looking at!
Taking the approach you've embarked on, your frame code needs to keep track of the Window object it's actually being hosted in, and then use that reference for dealing with the update.
That said, that entire approach is flawed. The navigation should be modeled in a view model data structure, activated via an ICommand object, and optionally via timer (as you seem to be doing here). Frame source and button state can be manipulated through bindings to properties in your view model data structure.
But, at the end of the day, the code you've got should work fine, once you start using the correct Window object.
I need basically an event that triggers at each 200 records loaded, so more data can be loaded until the end of data.
I tried to extend CharmListCell and using the method updateItem like this:
#Override
public void updateItem(Model item, boolean empty) {
super.updateItem(item, empty);
currentItem = item;
if (!empty && item != null) {
update();
setGraphic(slidingTile);
} else {
setGraphic(null);
}
System.out.println(getIndex());
}
But the System.out.println(getIndex()); method returns -1;
I would like to call my backend method when the scroll down gets the end of last fetched block and so on, until get the end of data like the "infinite scroll" technique.
Thanks!
The CharmListCell doesn't expose the index of the underlying listView, but even if it did, that wouldn't be of much help to find out if you are scrolling over the end of the current list or not.
I'd suggest a different approach, which is also valid for a regular ListView, with the advantage of having the CharmListView features (mainly headers and the refresh indicator).
This short sample, created with a single view project using the Gluon IDE plugin and Charm 5.0.0, shows how to create a CharmListView control, and fill it with 30 items at a time. I haven't provided a factory cell, nor the headers, and for the sake of simplicity I'm just adding consecutive integers.
With a lookup, and after the view is shown (so the listView is added to the scene) we find the vertical ScrollBar of the listView, and then we add a listener to track its position. When it gets closer to 1, we simulate the load of another batch of items, with a pause transition that represents a heavy task.
Note the use of the refresh indicator. When new data is added, we scroll back to the first of the new items, so we can keep scrolling again.
public class BasicView extends View {
private final ObservableList<Integer> data;
private CharmListView<Integer, Integer> listView;
private final int batchSize = 30;
private PauseTransition pause;
public BasicView() {
data = FXCollections.observableArrayList();
listView = new CharmListView<>(data);
setOnShown(e -> {
ScrollBar scrollBar = null;
for (Node bar : listView.lookupAll(".scroll-bar")) {
if (bar instanceof ScrollBar && ((ScrollBar) bar).getOrientation().equals(Orientation.VERTICAL)) {
scrollBar = (ScrollBar) bar;
break;
}
}
if (scrollBar != null) {
scrollBar.valueProperty().addListener((obs, ov, nv) -> {
if (nv.doubleValue() > 0.95) {
addBatch();
}
});
addBatch();
}
});
setCenter(new VBox(listView));
}
private void addBatch() {
listView.setRefreshIndicatorVisible(true);
if (pause == null) {
pause = new PauseTransition(Duration.seconds(1));
pause.setOnFinished(f -> {
int size = data.size();
List<Integer> list = new ArrayList<>();
for (int i = size; i < size + batchSize; i++) {
list.add(i);
}
data.addAll(list);
listView.scrollTo(list.get(0));
listView.setRefreshIndicatorVisible(false);
});
} else {
pause.stop();
}
pause.playFromStart();
}
}
Note also that you could benefit from the setOnPullToRefresh() method, at any time. For instance, if you add this:
listView.setOnPullToRefresh(e -> addBatch());
whenever you go to the top of the list and drag it down (on a mobile device), it will make another call to load a new batch of items. Obviously, this is the opposite behavior as the "infinite scrolling", but it is possible as well with the CharmListView control.
I want to get the index of selected row when user double clicks on a row.
Here is my code:
tab.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
int selectedRow = tab.getSelectedRow();
try {
String file = rows[selectedRow][2];
String path = "C:\\Users\\raj kumar\\Gallery\\" + file;
JLabel fileLable = new JLabel();
fileLable.setBounds(500, 600, 300, 300);
fileLable.setIcon(new ImageIcon(path));
pan.add(fileLable);
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
});
But the tab.getSelectedRow() returns -1 even though I double clicked the row in the table.
You want to know on which row your mouse points, but you ask which row is selected. So the simple solution is, instead of
int selectedRow = tab.getSelectedRow();
you can use
int row = tab.rowAtPoint(e.getPoint());
to get the wanted row. The Event e has every necessary information you need. The e.getPoint() returns the exact Point your cursor is currently located. And the rowAtPoint() should be self explaining.
This also makes sure that you only work with one row at a time, if this is important to you. I don't know how getSelectedRow() works if multiple rows are selected.
I want to create a wizard control from the pivot control. To achieve this I need to stop the pivot looping. I want to stop the pivot control moving forward from the last item to the first and backwards from the first to the last.
I'm pretty sure I should be able to intercept the manipulations e.g. cancel if I detect a right to left manipulation on the last pivot item. I can capture this in ManipulationDelta but don't know how to cancel the manipulation.
I have tried setting e.Handled = True but it didn't work.
I tried to set IsHitTestVisisble to false but this kills all manipulations. I tried setting it back to true in ManipulationCompleted but this then allows all manipulations.
Any ideas?
Cheers
Steve
The pivot is not designed to be used as a wizard and does not support stopping it's looping behaviour as this would create an inconsistent UX for users.
If you really must create a wizard do it with multiple pages.
Don't use a Pivot for a Wizard. Create your own transitions instead.
I couldn't reply to your comment on Matts answer but I just wanted to point you to this:
http://forty3degrees.wordpress.com/2011/07/19/creating-a-swipable-contentcontrol/
It's the last entry in my very neglected blog and should provide a good base for creating a wizard using a pivot style swipe.
Calum.
EDIT: I tried to do what you wanted with the pivot but couldn't find a way to stop it looping. The only way that I can think of to achieve this would be to derive a custom control from Pivot. Unfortunately SelectedIndex/SelectedItem are not virtual so you would need to hide them (with the new modifier) and reproduce the logic from the base class.
It's just an alternative solution I've posted here - you can try to make use of XNA framework TouchPanel and Touch.FrameReported Event:
using Microsoft.Xna.Framework.Input;
public MainPage()
{
InitializeComponent();
myPivot.IsHitTestVisible = false; // disable your Pivot
Touch.FrameReported += Touch_FrameReported;
TouchPanel.EnabledGestures = GestureType.HorizontalDrag;
}
TouchPoint first;
private void Touch_FrameReported(object sender, TouchFrameEventArgs e)
{
TouchPoint mainTouch = e.GetPrimaryTouchPoint(this);
if (mainTouch.Action == TouchAction.Down)
first = mainTouch;
else if (mainTouch.Action == TouchAction.Up && TouchPanel.IsGestureAvailable)
{
if (mainTouch.Position.X < first.Position.X)
{
if (myPivot.SelectedIndex < myPivot.Items.Count - 1)
myPivot.SelectedIndex++;
}
else if (mainTouch.Position.X > first.Position.X)
{
if (myPivot.SelectedIndex > 0)
myPivot.SelectedIndex--;
}
}
}
Thought it would probably work from WP7.1 as TouchPanel is available from that version of the OS.
If you absolutely want to keep the Pivot from looping, here is a quick and dirty hack:
int previousSelectedIndex = 0;
public PageWithPivot()
{
InitializeComponent();
pivot.SelectionChanged += new SelectionChangedEventHandler(pivot_SelectionChanged);
}
private void pivot_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (pivot.SelectedIndex == 0 && previousSelectedIndex == <number Of screens - 1>)
pivot.SelectedIndex = <number Of screens - 1>;
previousSelectedIndex = pivot.SelectedIndex;
}
This causes your PivotControl to jump back to the last pivotItem. Not very pretty but works.
This is so weird because it only works in the Emulator. I guess you shan't mess with the UI
You can use MVVM:
<phone:Pivot Foreground="Black"
Name="pivot1"
Title="AIDE"
SelectedIndex="{Binding SelectedItem, Mode=TwoWay}">
Cs:
private class HelpViewModel : ViewModelBase
{
public HelpViewModel()
{
}
private int _SelectedItem = 0;
public int SelectedItem
{
get
{
return _SelectedItem;
}
set
{
if (_SelectedItem != value)
{
if (value == 3)
_SelectedItem = 0;
else
_SelectedItem = value;
RaisePropertyChanged(() => SelectedItem);
}
}
}
}
public AppHelpPivot()
{
InitializeComponent();
LayoutRoot.DataContext = new HelpViewModel();
}