Filepicker in WP8.1 app did not show any photo - vb.net

I need to make instrument, that allows users to choose photo from Gallery. After choosing photo, it will be shown to the user in ImageBox.
Problem is, that when user chooses some photo in Gallery, Gallery closes, ImageBox stays empty. Code returns no error. Please help me to find error and solve this problem. Thank you.
Here is a code:
ImagePath = String.Empty
filePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary
filePicker.ViewMode = PickerViewMode.Thumbnail
' Filter to include a sample subset of file types
filePicker.FileTypeFilter.Clear()
filePicker.FileTypeFilter.Add(".bmp")
filePicker.FileTypeFilter.Add(".png")
filePicker.FileTypeFilter.Add(".jpeg")
filePicker.FileTypeFilter.Add(".jpg")
filePicker.PickSingleFileAndContinue()
Dim BitmapImage = New BitmapImage()
Await BitmapImage.SetSourceAsync(filePicker)
MyPhoto.Source = BitmapImage

If you are using filePicker.PickSingleFileAndContinue() you need to add code into the App_Activated
You will notice that PickSingleFileAndContinue() is a void method will not return the picked file were as PickSingleFileAsync() will return a file.
Code block is in C#,sorry i have only limited knowledge in vb, you can find vb sample below
Similar SO Answer
C#
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".png");
StorageFile file = await openPicker.PickSingleFileAsync();
As your are using PickSingleFileAndContinue() you need to implement ContinuationManager that were you get the file you picked.
In the App.xaml.cs
public ContinuationManager ContinuationManager { get; private set; }
This will fire when the app get activated
protected async override void OnActivated(IActivatedEventArgs e)
{
base.OnActivated(e);
continuationManager = new ContinuationManager();
Frame rootFrame = CreateRootFrame();
await RestoreStatusAsync(e.PreviousExecutionState);
if(rootFrame.Content == null)
{
rootFrame.Navigate(typeof(MainPage));
}
var continuationEventArgs = e as IContinuationActivatedEventArgs;
if (continuationEventArgs != null)
{
Frame scenarioFrame = MainPage.Current.FindName("ScenarioFrame") as Frame;
if (scenarioFrame != null)
{
// Call ContinuationManager to handle continuation activation
continuationManager.Continue(continuationEventArgs, scenarioFrame);
}
}
Window.Current.Activate();
}
Usage in the page
Assume that one page of your app contains code that calls a FileOpenPicker to pick an existing file. In this class, implement the corresponding interface from the ContinuationManager helper class. When your app uses a FileOpenPicker, the interface to implement is IFileOpenPickerContinuable.
public sealed partial class Scenario1 : Page, IFileOpenPickerContinuable
{
...
//inside this you have this
private void PickAFileButton_Click(object sender, RoutedEventArgs e)
{
...
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".png");
// Launch file open picker and caller app is suspended
// and may be terminated if required
openPicker.PickSingleFileAndContinue();
}
}
switch (args.Kind)
{
case ActivationKind.PickFileContinuation:
var fileOpenPickerPage = rootFrame.Content as IFileOpenPickerContinuable;
if (fileOpenPickerPage != null)
{
fileOpenPickerPage.ContinueFileOpenPicker(args as FileOpenPickerContinuationEventArgs);
}
break;
...
}
Download msdn sample here
Msdn documentation using FilePicker

Related

Xamarin.Android how to remember the position of items in a recyclerview

I have a recyclerview set up in xamarin.android as per the code in this link
https://www.appliedcodelog.com/2019/08/reorder-list-items-by-drag-and-drop-in.html
My question is, how can I remember the position of these items when the app is restarted etc. When the user adds items they are inserted at adapter position 0,1,2,3 etc but when they close the app and come back in, it is not always in the same order.
The user can also rearrange by drag and drop so this seems to add even more confusion!
Currently I have the items in the recyclerview being saved by converting the list to Json and loading when the app opens again but as I said, the items aren't always in the same order as before the app was closed.
Can anyone advise the best way to do this? I have tried to add the item name and position number to a list converting to json then trying to insert the item at the saved position index but can't get it to work..
Thanks
Do you want to achieve the result like following GIF?
You can use PreferenceManager to store position of items(Before store data, I will Serialize data) in a recyclerview.
You can override OnPause() method, this method will be executed when application is background or app is killed. So we can store the position and data in this method.Here is code about ReOrderActivity
[Activity(Label = "ReOrderList")]
public class ReOrderActivity : Activity, IOnStartDragListener
{
private ItemTouchHelper _mItemTouchHelper;
public static ObservableCollection<string> ResourceList;
private RecyclerView _resourceReorderRecyclerView;
ReOrderAdapters resourceAdapter;
ISharedPreferences prefs;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.ReOrderLayout);
prefs = PreferenceManager.GetDefaultSharedPreferences(this);
GetCollection();
resourceAdapter = new ReOrderAdapters(ResourceList, this);
// Initialize the recycler view.
_resourceReorderRecyclerView = FindViewById<RecyclerView>(Resource.Id.ResourceReorderRecyclerView);
Button mDone = FindViewById<Button>(Resource.Id.mDone);
mDone.Click += MDone_Click;
_resourceReorderRecyclerView.SetLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.Vertical, false));
_resourceReorderRecyclerView.SetAdapter(resourceAdapter);
_resourceReorderRecyclerView.HasFixedSize = true;
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(resourceAdapter);
_mItemTouchHelper = new ItemTouchHelper(callback);
_mItemTouchHelper.AttachToRecyclerView(_resourceReorderRecyclerView);
}
protected override void OnPause()
{
base.OnPause();
string ConvertData = JsonConvert.SerializeObject(ResourceList);
ISharedPreferencesEditor editor = prefs.Edit();
editor.PutString("ObservableCollection_ConvertData", ConvertData);
// editor.Commit(); // applies changes synchronously on older APIs
editor.Apply(); // applies changes asynchronously on newer APIs
}
private void MDone_Click(object sender, System.EventArgs e)
{
resourceAdapter.AddItem("Add item");
}
public void OnStartDrag(RecyclerView.ViewHolder viewHolder)
{
_mItemTouchHelper.StartDrag(viewHolder);
}
//Added sample data record here
public void GetCollection()
{
//ISharedPreferencesEditor editor = prefs.Edit();
//editor.PutString("ObservableCollection_ConvertData", "");
//editor.Apply();
string ConvertData = prefs.GetString("ObservableCollection_ConvertData","");
if(string.IsNullOrEmpty(ConvertData))
{
ResourceList = new ObservableCollection<string>();
ResourceList.Add("OnPause()");
ResourceList.Add("OnStart()");
ResourceList.Add("OnCreate()");
}
else
{
ResourceList= JsonConvert.DeserializeObject<ObservableCollection<string>>(ConvertData);
}
//var or= ResourceList.ToString();
}
}
}
You can download my demo
https://drive.google.com/file/d/1mQTKf3rlcIVnf2N97amrqtnrSCRk-8ZW/view?usp=sharing

How to check if an application is it's first run or not in xamarin crosspaltform

I want to show some pages in the first time app is installed, and the next time when I open the app show some other pages.
I tried this code
protected override void OnStart()
{
if (Application.Current.Properties.ContainsKey("id"))
{
MainPage = new NavigationPage(new Page2());
}
else
{
Application.Current.Properties["id"] = 2;
MainPage = new NavigationPage(new Page1());
}
}
The values in the Properties dictionary are only stored when the app goes to sleep
For a cross-platform approach, you can use the Settings Plugin
Then you can create a boolean property, for example, DidOpenOnce, and if it is false, show your initial welcome page or whatever. Then afterwards, set it to true.
protected void checkApplicationInstallState()
{
//retreive
var prefs = Application.Context.GetSharedPreferences("MyApp", FileCreationMode.Private);
var somePref = prefs.GetBool("IsApplicationOpenedForOnce", null);
if (!somePref) {
// Your Application is opened for the very first time. Now change the value to true as you have now opened the app so next time opening this application should get a true value.
var prefEditor = prefs.Edit();
prefEditor.PutBool(true, "IsApplicationOpenedForOnce");
prefEditor.Commit();
}
}
public MainPage()
{
InitializeComponent();
if (Application.Current.Properties.ContainsKey("FirstUse"))
{
//Do things when it's NOT the first use...
loadinit();
}
else
{
Application.Current.Properties["FirstUse"] = false;
//Do things when it IS the first use...
}
}
public async void loadinit()
{
await Navigation.PushAsync(new LoadPage());
}

Refresh View in Xamarin BindingContext

I have a simple application using PCL for Xamarin, Inside my view called lvl1.xaml.cs I have a method calling for a new question from the db
public lvl1()
{
ques = App.Database.GetQuest();
user = App.database.GetUser();
BindingContext = ques;
correctAns = ques.correctAns;
InitializeComponent();
}
The problem is, I have a DisplayAlert to say if the answer was correct or not, but I want to load a new question as soon as the user click continue, so I have this function (also inside lvl1.xaml.cs), when I debbug, I see that it goes to the constructor, gets the new question, but the view still displays the old question, how can I refresh it/ bind it correctly
async void GameContinue(bool continues)
{
if (continues)
{
var lvl = new lvl1();
}
else
{
await Navigation.PopToRootAsync();
}
}
Thanks!
When you call var lvl = new lvl1() it is creating the new page in the background of the app, but you never actually navigate to it. That is why you don't see a new question. You need to call Navigation.PushAsnyc(lvl); in order to actually display the new page you created.
You may also want to create a separate method to get a new question so you don't need to create a new page every time.
asnyc void getNewQuestion()
{
//Get question from db and set the binding context
ques = App.Database.GetQuest();
user = App.database.GetUser();
BindingContext = ques;
correctAns = ques.correctAns;
}
Then in your constructor:
public lvl1()
{
getNewQuestion();
InitializeComponent();
}
and after the DisplayAlert:
async void GameContinue(bool continues)
{
if (continues)
{
getNewQuestion();
}
else
{
await Navigation.PopToRootAsync();
}
}

Is it somehow possible to have two master views and one detail view?

If I have for example one master view on the left and one in the middle, each showing oder Java Beans/POJOs, can I use a shared detail view that somehow listens to the active beans of each view and then displays the currently selected one in more detail? A one to one relation is quite easy to manage by using your Context library.
#ViewDocking(areaId ="left", position=1, displayName="Profiles", menuEntry = #WindowMenuEntry(path = "", position=0), accelerator="Shortcut+1")
public class ProfileListView extends BorderPane implements LocalContextProvider {
private final SimpleContextContent content = new SimpleContextContent();
private final SimpleContext context = new SimpleContext(content);
#FXML
private ListView<Profile> listview;
public ProfileListView() {
load();
// add some profiles
listview.getItems().add(new Profile("Profile1"));
listview.getItems().add(new Profile("Profile2"));
listview.getItems().add(new Profile("Profile3"));
// setup selection listener
listview.getSelectionModel().selectedItemProperty().addListener((value, oldProfile, newProfile) -> {
// set active profile and remove old one
content.remove(oldProfile);
content.add(newProfile);
});
// setup double click listener
configureClickListener();
}
private Profile getSelectedProfile() {
return listview.getSelectionModel().getSelectedItem();
}
private void configureClickListener() {
listview.setOnMouseClicked(event -> {
// check if it was a double click
if(event.getClickCount() == 2) {
System.out.println(getSelectedProfile());
// inject into editor pane
// calls the procedure to create a tab in the center area...
}
});
}
private void load() {
FXMLLoaders.loadRoot(this);
}
#Override
public Context getLocalContext() {
return context;
}
}
This is one master view holding a list view of items.
The other one would be the same, docking to the right as another tab and holding POJOs of type 'Action'.
The detail view is here:
#ViewDocking(areaId = "right", displayName = "Properties", accelerator = "Shortcut+2", menuEntry = #WindowMenuEntry(path = "", position = 0), position = 1)
public class ProfilePropertiesView extends BorderPane implements LocalContextProvider, ActiveContextSensitive {
private Context activeContext;
private SimpleContextContent content = new SimpleContextContent();
private SimpleContext context = new SimpleContext(content);
private Profile profile;
private IWindowService service = new NullWindowService();
#FXML
private PropertySheet propertysheet;
public ProfilePropertiesView() {
load();
// retrieve framework service, TODO: use tracker
BundleContext ctx = FrameworkUtil.getBundle(getClass()).getBundleContext();
service = ctx.getService(ctx.getServiceReference(IWindowService.class));
// initialize callback
service.addCallback(title -> {
System.out.println("callback called " + title);
// update the property sheet ui by re-creating the items list
// updateUI();
// we can safely return null
return null;
});
// configure editor factory so the user is able to use a combobox
propertysheet.setPropertyEditorFactory(new CustomPropertyEditorFactory(service));
}
private void load() {
FXMLLoaders.loadRoot(this);
}
#Override
public Context getLocalContext() {
return context;
}
private void contextChanged() {
// find profile information
Profile found = activeContext.find(Profile.class);
// if the found profile is null, ignore it
if (found != null) {
// reset if profile is valid
if (profile != null) {
reset();
}
// create reference and register
profile = found;
register();
}
}
private void register() {
// retrieve observablelist of bean properties if some profile is selected
if(profile != null) {
ObservableList<Item> items = createDetailedList(profile);
propertysheet.getItems().setAll(items);
}
}
private void updateUI() {
// clear property elements and re-create them
reset();
// re-create items
ObservableList<Item> items = createDetailedList(profile);
propertysheet.getItems().addAll(items);
}
private ObservableList<Item> createDetailedList(Object bean) {
ObservableList<Item> list = FXCollections.observableArrayList();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass(), Object.class);
Arrays.stream(beanInfo.getPropertyDescriptors()).map(pd -> new DetailedBeanProperty(bean, pd)).forEach(list::add);
} catch (IntrospectionException e) {
e.printStackTrace();
}
return list;
}
private void reset() {
propertysheet.getItems().clear();
}
#Override
public void setActiveContext(Context activeContext) {
this.activeContext = activeContext;
this.activeContext.addContextListener(Profile.class, event -> contextChanged());
// trigger change
contextChanged();
}
}
The current ProfilePropertiesView is just configured to display the properties of the selected profile. I want it to be able to display the current information of the last selected POJO in the UI. That means that if the user selected a Profile from the ListView, that profile should be displayed in the properties view. If he selected an Action from the Table (which is displayed in the center), the properties of the Action should be displayed.
Do I just need to register a new ContextListener for the Action.class
POJO and then call a method to populate the PropertiesView? I was
unsure if this is the right solution...
Yes, just add another ContextListener to the activeContext for every POJO type you want to observe.
Also note that in the constructor of views it's better to use a ServiceTracker instead of looking for the service via BundleContext as the service might not be available yet, depending on the order the bundles are loaded.
You can find a sample which uses a ServiceTracker here: https://stackoverflow.com/a/35974498/506855

Windows Store apps, save and load the state of Bing Maps Pushpins on navigation between pages

I'm making a Windows Store App that asks for user input then produces a bunch of pushpins based on that input. When a pushpin is tapped the app navigates to a page with more detail.
Now the problem i'm having is this:
My pages all inherit from the automatically generated LayoutAwarePage so I could potentially make use of SaveState and LoadState to save the pushpins so they don't get wiped on navigation. The thing is that i can't get the pins to save into the Dictionary object supplied by SaveState.
The error I get is "Value cannot be null" and it's referring to the _pageKey variable in LayoutAwarePage.OnNavigatedFrom() and i don't know why it's happening.
I've tried serialising them into a JSON string so i can deserialise it in LoadState, but i get the same result using a string or a List of UIelement.
I think this is all due to my lack of understanding of how SaveState, LayoutAwarePAge and SuspensionManager work. I thought what i was doing would work as the Dictionary is only asking for a string and an object.
I'm not using any other methods from LayoutAwarePage so if there is a better way than using SaveState and LoadState, I'm all ears.
These are the two versions of SaveState i've tried:
Using JSON
protected override void SaveState(Dictionary<String, Object> pageState)
{
List<string> pindata = new List<string>();
List<string> serialisedpins = new List<string>();
foreach (Pushpin ele in map.Children)
{
pindata = ele.Tag as List<string>;
serialisedpins.Add(JsonConvert.SerializeObject(pindata));
}
string jasoned = JsonConvert.SerializeObject(serialisedpins);
pageState["pins"] = jasoned;
}
using a List of UIElement
protected override void SaveState(Dictionary<String, Object> pageState)
{
List<UIElement> pins = new List<UIElement>(map.Children);
pageState["pins"] = pins;
}
The error you're getting (_pagekey value cannot be null) is not really related to what you're saving into the Dictionary. The exception is most likely being thrown in OnNavigateFrom() method of LayoutAwarePage:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
var frameState = SuspensionManager.SessionStateForFrame(this.Frame);
var pageState = new Dictionary<String, Object>();
this.SaveState(pageState);
frameState[_pageKey] = pageState; // <-- throws exception because _pageKey is null
}
If you take a look at the rest of the code of LayoutAwarePage you'll find out the value of _pageKey is being set in OnNavigatedTo method of LayoutAwarePage:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// Returning to a cached page through navigation shouldn't trigger state loading
if (this._pageKey != null) return;
var frameState = SuspensionManager.SessionStateForFrame(this.Frame);
this._pageKey = "Page-" + this.Frame.BackStackDepth; <-- this line sets the _pageKey value
if (e.NavigationMode == NavigationMode.New)
{
// Clear existing state for forward navigation when adding a new page to the
// navigation stack
var nextPageKey = this._pageKey;
int nextPageIndex = this.Frame.BackStackDepth;
while (frameState.Remove(nextPageKey))
{
nextPageIndex++;
nextPageKey = "Page-" + nextPageIndex;
}
// Pass the navigation parameter to the new page
this.LoadState(e.Parameter, null);
}
else
{
// Pass the navigation parameter and preserved page state to the page, using
// the same strategy for loading suspended state and recreating pages discarded
// from cache
this.LoadState(e.Parameter, (Dictionary<String, Object>)frameState[this._pageKey]);
}
}
Usually the reason for that is that you're overriding OnNavigatedTo in your own page without calling base.OnNavigatedTo(e) inside it. The basic pattern of overriding it should always be:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
// the rest of your own code
}
This will make sure the base implementation will execute and set the _pageKey value as well as call LoadState() to load the previously saved state if there's any.