Slow style binding in my windows store app - xaml

I have some buttons in my xaml which I want to bind the style dynamically based on some value. This all works great, but for maybe a second or two the buttons are not styled properly as my app is still loading. My application will load, but I have a list view that is waiting to receive some data from a web service. It seems as though the buttons won't be bound until the list view is bound.
Is there a way to set a "default" style on my buttons but still have my buttons bind at runtime without having to set all the properties for each button? Or why are my buttons taking so long to bind? Can I prioritize them?
Here is my button...
<Button x:Name="ButtonAll" Click="ButtonAll_Click" Style="{Binding State,Converter={StaticResource ButtonStateConverter},ConverterParameter=All}" Margin="0,0,50,0">All</Button>
Here is my converter code...
SampleState state = (SampleState)value;
SampleState param = new SampleState() { Code = (string)parameter, Name = (string) parameter };
if (state == param)
return App.Current.Resources["TextPrimaryButtonStyle"];
else
return App.Current.Resources["TextSecondaryButtonStyle"];

Related

Vue lazyloading gets triggered when adding dynamic class to <main>

I am adding a 'sticky-header' class to my dynamically, but when its sticky i obviously also need to add padding to my so the content doesnt go behind the header.
The problem is that when adding the padding via class-binding(v-bind:class="{'fixed-header': stickyHeader}")on scroll, this reloads all the lazy-loaded images (that are lazy loaded using vue lazy)
This makes all images go from loading to loaded in a split second, but its very noticable.
stickyHeaderis a boolean that gets recalculated on scroll, if the window is scrolled past a certain element (with a eventlistener on scroll: checkHeader())
checkHeader() {
var elementTarget = document.getElementById("notice");
if(window.scrollY > (elementTarget.offsetTop + elementTarget.offsetHeight)){
this.stickyHeader = true;
}
else{
this.stickyHeader = false;
}
}
Anyone know what exactly triggers the images to go back to 'loading' for a split second?
To solve this instead of dynamically binding the class with v-bind i simply add it in the scroll listener method with basic javascript, now it doesnt rerender :) !

Implementing Detachable Panel in UWP App

I have an Image in a grid where I display some custom content by setting the Image's source to a WritableBitmap and updating the bitmap. What I want to do is to implement a "detach" button that will put my Image on a separate window allowing the user to move it to a different screen, resize it etc. independent of my main app window. If the new window is closed, I would like to bring it back to its original spot. While the Image is on the new window, I want to continuously update it with new content via updating source bitmap (as it would have been before it was detached).
I initially thought I would be able to create a new window and "move" my Image control there by first removing it from its original parent then adding it as a child to a layout in the new window. I used the code below:
CoreApplicationView^ newCoreView = CoreApplication::CreateNewView();
int mainViewId = Windows::UI::ViewManagement::ApplicationView::GetApplicationViewIdForWindow(
CoreApplication::MainView->CoreWindow);
uint indexOfObjectToDetach = -1;
bool found = originalGrid->Children->IndexOf(imageToMove, &indexOfObjectToDetach);
if(found)
{
myGrid->Children->RemoveAt(indexOfObjectToDetach);
}
DispatchedHandler^ dispatchHandler = ref new DispatchedHandler([this, mainViewId]()
{
newView_ = Windows::UI::ViewManagement::ApplicationView::GetForCurrentView();
Windows::UI::Xaml::Controls::StackPanel^ newWindowGrid = ref new Windows::UI::Xaml::Controls::StackPanel();
Window::Current->Content = newWindowGrid;
Window::Current->Activate();
newWindowGrid->Children->Append(imageToMove); // Add to new parent
});
create_task(newCoreView->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, dispatchHandler)).then([this, mainViewId]()
{
auto a = newView_->Id;
create_task(ApplicationViewSwitcher::TryShowAsStandaloneAsync(a, ViewSizePreference::Default, mainViewId, ViewSizePreference::Default));
});
However in the line where I add the Image to its new parent, I get an Interface was marshalled for a different thread error. Upon more reading, this is due to the fact that each new window is in its own thread and I'm moving an object to another thread.
I am new to UWP and I am not sure how to approach implementing this UI behavior. How do I access/transfer my state in one view to another ?
The problem is indeed the fact that each application view in UWP has its own thread and its own UI dispatcher. When you create a control, it is tied to the UI thread it was created on, hence you cannot place it onto another application view.
The solution is to create the new Image next to the StackPanel within the new view's UI thread. I don't really use C++, but in C# I would implement it as follows:
await newCoreView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
StackPanel panel = new StackPanel();
Image image = new Image();
panel.Children.Add( panel );
image.Source = ...; //your source
Window.Current.Content = frame;
Window.Current.Activate();
newViewId = ApplicationView.GetForCurrentView().Id;
});
To further clarify - you can safely "transfer" normal data types into other view, the problem is mainly with the UI-tied types like controls, pages, etc.

Windows 8 app: How to pass a parameter on GoBack()?

There are a lot of samples showing how to pass a parameter on navigating to a page in Window 8 (WinRT). But I could not find any hint for passing parameters going back.
Situation: The user navigates to a details page of same data. The data is passed to the page by
Frame.Navigate(typeof(DedtailsPage), data);
How can I pass back the changed data on GoBack()?
Store the reference to data somewhere and retrieve it when you navigate back?
Also note that it's best not to pass objects other than simple strings or values between pages, since only simple types are supported for storing frame navigation state in case your app gets suspended.
I know, that this is a very bad idea, but usualy I use this:
To write:
Frame rootFrame = Window.Current.Content as Frame;
rootFrame.Tag = myObject1;
To read:
Frame rootFrame = Window.Current.Content as Frame;
var myObject2 = rootFrame.Tag;
I've made another choice to handle this.
Keep in mind that I'm a Xamarin developer (not Forms!) so i was looking for a solution which was similar for all platforms: iOS, Android and Windows.
I am a great fun of events, rather than passing objects or storing globals.
So the best choice to pass data from PageB (the child) to PageA (the parent) is to communicate via events.
Some notes: In iOS and Android, when you navigate from a "page" to "page" you can do this by passing an instance of the target object you want to navigate to. In iOS you create an instance of a custom UIViewController. In Android you create an instance of a custom Fragment. Doing this allow you to attach events handler to your instances.
An example:
var controller = new ExtrasViewController();
controller.ExtraSelected += ExtrasFragment_ExtraSelected;
controller.ExtrasCleared += ExtrasFragment_ExtrasCleared;
this.NavigationController.PushViewController(controller, false);
In WinRT Apps you are only allowed to pass "types" of target page to navigate to. So the only way to attach event handlers to your page instance is to use the OnNavigatedFrom method from the calling page. So suppose you are in PageA and want to attach some event handlers to your PageB, before it become active, simply write in your PageA "code behind":
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
var page = e.Content as ExtraBody;
if(page != null)
{
page.ExtraSelected += ExtrasFragment_ExtraSelected;
page.ExtrasCleared += ExtrasFragment_ExtrasCleared;
}
}

WinJS AppBar button flash on Hide

My application has a WinJS AppBar control at the bottom of the screen. I use .showOnlyCommands(buttonsToShowArray) to show and hide buttons on ListView itemSelectionChanged event.
The problem I have right now is that when every I call .showOnlyCommands, the buttons to be hidden (or you may say "replaced") are going to flash on the top of the screen.
I tried to use the Microsoft sample app, this doesn't happen. I tried to use .showCommands + .hideCommands method, it is the same behavior. Note that this didn't happen before the Release Preview version of Win8.
I have no idea what is going on. Any idea?
EDIT:
I did further investigation, the problem happens on hideCommands. Say I have 3 buttons displayed on the appbar. I call hideCommands to hide all 3 buttons. The icon of the 3 buttons would disappear on the appbar, then pile up at the top-left corner of the screen and then disappear. (i.e. there would be a flash of 3 piled up buttons at the corner of the screen).
You may be invoking showOnlyCommands when the AppBar is in the process of 'showing'. I've found that when calling these methods in the beforeshow or aftershow handler that this happens. This quote from Animating your UI sheds light on why:
Use fade in and fade out animations to show or hide transient UI or controls. One example is in an app bar in which new controls can appear due to user interaction.
The sample app shows/hides the buttons before the appbar is shown. You may be calling show on the app bar before calling showOnlyCommands.
A temporary hack for this problem is:
Set the button be invisible before calling showOnlyCommands or HideCommands.
Here is the code that I use for now:
/*
* #param {WinJS.UI.AppBar} appbar winControl
* #param {Array} array of appbar buttons to be shown
*/
function showOnlyCommands(appbarControl, buttonsToShow) {
var toShow = {};
for (var i = 0; i < buttonsToShow.length; i++) {
toShow[buttonsToShow[i].id] = true;
}
for (var i = 0; i < visibleButtonsList.length; i++) {
var id = visibleButtonsList[i].id;
if (!toShow[id]) {
// set the display property of the buttons to be hidden to "none"
var button = document.getElementById(id);
if (button) {
button.style.display = 'none';
}
}
}
// update the visible buttons list
visibleButtonsList = buttonsToShow;
// Note that we don't need to set the "display" property back for the buttons,
// because WinJS.UI.AppBar.showOnlyCommands would set it back internally
appbarControl.showOnlyCommands(buttonsToShow);
}

Change applicationbar buttonicon at runtime

I'm developing a WP7 app and the application needs to change the icon of a button on the application bar given the state of a request.
I have tried:
if (App.Servers[index].ServerState == "Enabled")
{
DetailsAppBar.btnStart.IconUri = new Uri("/AppBar/appbar.stop.rest.png");
}
else
{
DetailsAppBar.btnStart.IconUri = new Uri("/AppBar/appbar.transport.play.rest.png");
}
This doesn't give me an error in the code, but it can't compile....
any hints to do this is appreciated :)
thanks
ApplicationBar is a special control that does not behave as other Silverlight controls (see Peter Torr's post on the subject). One of the consequences is that names given in XAML to app bar buttons generate fields in code-behind that are always null.
I'm guessing that in your case the btnStart field in DetailsAppBar is set to null, and thus trying to set its IconUri property results in a NullReferenceException being thrown.
To access a button in an application bar, you must instead reference it by its zero-based index in the buttons list. For instance, the code below returns a reference to the third button in the app bar:
button = (IApplicationBarIconButton)ApplicationBar.Buttons[2];
figured it out...
((ApplicationBarIconButton)ApplicationBar.Buttons[2]).IconUri = new Uri("/AppBar/appbar.stop.rest.png",UriKind.Relative);
did the trick :)