I createt ResourceDictionary in App.xaml file for application header.
In header I created two dropdowns menu (with stacklayouts and grids).
First is for some user informations and second one is for search.
By default these dropdown menus are hiden.
Max one may be visible if user click on user-icon or on search-icon.
So in HeaderViewModel I cratet these two methods:
private async void AccountInformationAsync()
{
var userService = await UserService.GetUserData();
Username = userService.Username;
DisplayName = userService.DisplayName;
Status = userService.Status;
Influence = userService.Influence;
MTP = userService.MTP;
VisibilityInformation = !VisibilityInformation;
if (VisibilityInformation == true)
{
VisibilitySearch = false;
}
}
private void Search()
{
VisibilitySearch = !VisibilitySearch;
if (VisibilitySearch == true)
{
VisibilityInformation = false;
}
}
This works fine... If user click on user-icon user info will show up and if user then click on serach-icon info will hide an search menu will show up.
So, my question is how to hide any of these menus if user click somewhere else on the screen?
You need to add an TapGestureRecognizer on the Main Layout View of the Page. And on the Tap of it you can use Command and Hide both the dropdown Menu.
private void HideDropDowns()
{
VisibilitySearch = false;
VisibilityInformation = false;
}
HideDropDowns should be the Method assigned to the Command in the TapGestureRecognizer.
Related
I have a simple chat bot that renders "on this day" facts based on Wikipedia.
As you can see, there's a button on my UI. I want that if the user taps on it, a new browser tab opens with given Wikipedia url.
Until now, I only see the possibility to send other messages using buttons and there action (PostMessageAction).
Do you have any tip on how to achieve my feature idea?
Code
private fun makeMessage(container: OnThisDay): ChatMessage {
return message {
...
section {
text("On this day (${container.date}) happened:")
container.happenings.reversed().forEach {
text(
size = MessageTextSize.SMALL,
content = "${it.year}:\n${it.description}",
)
controls {
wikipediaButton(it.wikipediaUrl) <-- BUTTON
}
divider()
}
}
}
}
private fun MessageControlGroupBuilder.wikipediaButton(urlString: String) {
val action = PostMessageAction("a", "b") <-- NO other action possible?
button("Open Wikipedia", action, MessageButtonStyle.SECONDARY)
}
Screenshot
You can use NavigateUrlAction for this. Here's an example:
message {
section {
controls {
button(
text = "Open Wikipedia",
style = MessageButtonStyle.PRIMARY,
action = NavigateUrlAction(
url = "https://wikipedia.org",
withBackUrl = false,
openInNewTab = true
)
)
}
}
}
How can I implement a vertical three dot menu in every table row, like here in this picture?
CUBA.platform has no built-in component that provides context menu on button click, but it can be easily implemented using Vaadin ContextMenu class.
The main concept is as follows:
unwrap Vaadin component:
CubaButton vButton = button.unwrap(CubaButton.class);
create a context menu for this component and add menu items:
ContextMenu contextMenu = new ContextMenu(vButton, true);
contextMenu.addItem("Item", (MenuBar.Command) selectedItem -> {
// handle menu item click
});
...
show the context menu programmatically on button click:
vButton.setClickHandler(clickEvent ->
contextMenu.open(clickEvent.getClientX(), clickEvent.getClientY()));
You can use this approach in the generated table column. Let's assume that we need a single-column table that displays all the data.
XML definition
<table id="usersTable"
dataContainer="usersDc"
columnHeaderVisible="false"
stylename="no-stripes"
width="250px"
height="400px">
<columns>
<column id="column"/>
</columns>
<buttonsPanel>
<button caption="Share" icon="USER_PLUS" stylename="borderless"/>
<button caption="Preview" icon="EYE" stylename="borderless"/>
</buttonsPanel>
</table>
Java Controller
#UiController("demo_Sandbox")
#UiDescriptor("sandbox.xml")
public class Sandbox extends Screen {
#Inject
private UiComponents uiComponents;
#Inject
private Notifications notifications;
#Inject
private MetadataTools metadataTools;
#Install(to = "usersTable.column", subject = "columnGenerator")
private Component usersTableColumnColumnGenerator(User user) {
HBoxLayout rootLayout = uiComponents.create(HBoxLayout.class);
rootLayout.setMargin(new MarginInfo(true, false, true, false));
rootLayout.setSpacing(true);
rootLayout.setWidthFull();
VBoxLayout content = uiComponents.create(VBoxLayout.class);
content.setSpacing(true);
Label<String> login = uiComponents.create(Label.TYPE_STRING);
login.setValue("Login: " + user.getLogin());
Label<String> name = uiComponents.create(Label.TYPE_STRING);
name.setValue("Name: " + user.getName());
content.add(login, name);
LinkButton contextMenu = uiComponents.create(LinkButton.class);
contextMenu.setIconFromSet(CubaIcon.ELLIPSIS_V);
contextMenu.setAlignment(Alignment.TOP_RIGHT);
setupContextMenu(contextMenu, user);
rootLayout.add(content, contextMenu);
return rootLayout;
}
private void setupContextMenu(LinkButton button, User user) {
CubaButton vButton = button.unwrap(CubaButton.class);
ContextMenu contextMenu = new ContextMenu(vButton, true);
addMenuItem(contextMenu, "Rename", user);
addMenuItem(contextMenu, "Delete", user);
addMenuItem(contextMenu, "Open", user);
vButton.setClickHandler(clickEvent ->
contextMenu.open(clickEvent.getClientX(), clickEvent.getClientY()));
}
private void addMenuItem(ContextMenu contextMenu, String caption, User user) {
contextMenu.addItem(caption, (MenuBar.Command) selectedItem ->
notifications.create()
.withCaption(caption + ": " + metadataTools.getInstanceName(user))
.show());
}
}
The result
Data is a generic List of domain objects.
I click the "Deploy Status" column header to sort on that column.
I have a button that does nothing more than folv.UpdateObject(someObject) .
Every time I press that button, the Deploy Status column maintains its sort, but all rows within the sorted blocks are randomly reordered, as per screenshot.
I have commented out everything in the form's code beyond loading the data, the test button, and the FastObjectListView's column.Add() and .SetObjects(). There are no event handlers wired up for the FastObjectListView. I am not setting PrimarySort or SecondarySort in code; only by clicking with the mouse.
You should be able to fix this problem by either calling Sort after your button's call to UpdateObject or changing your usage of UpdateObject to RefreshObject
Reproducing the problem (C# Repro for the issue in the API)
This seems to reproduce the problem you are having. Run the code, sort the Other column ascending. Click the update button.
public class MainForm : Form
{
public MainForm()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
//
// MainForm
//
this.ClientSize = new System.Drawing.Size(300, 300);
this.Name = "MainForm";
this.ResumeLayout(false);
this.PerformLayout();
var OLVa = new FastObjectListView();
OLVa.Width = 250;
OLVa.Height = 250;
OLVa.Columns.Add(new OLVColumn("ID", "ID"));
OLVa.Columns.Add(new OLVColumn("Other", "Other"));
var l1 = new lolz(1, 3);
OLVa.AddObject(l1);
OLVa.AddObject(new lolz(2,3));
this.Controls.Add(OLVa);
var btn = new Button()
{
Text = "Update",
Top = OLVa.Bottom
};
btn.Click += (s,e)=>OLVa.UpdateObject(l1);
this.Controls.Add(btn);
}
private class lolz
{
public int ID;
public int Other;
public lolz(int id, int other)
{
ID = id;
Other = other;
}
}
}
Fixing the problem
The following would fix it for the above example:
btn.Click += (s,e)=>
{
OLVa.BeginUpdate();
try
{
OLVa.UpdateObject(l1);
OLVa.Sort();
}
finally
{
OLVa.EndUpdate();
}
};
I navigate between pages with Navigation Helper class which VS 2013 added when solution created, But scroll state most of controls (Like Pivot, Hub) does not saved like in Windows Phone 8.x Silverlight.
What should I do for implement this behaviour? Should I handle scrolling state by myself and restore scroll when i go back in visited page?
Thanks.
UPDATE1:
I need save selected pivot/hub item etc, when i go back to page.
UPDATE2:
void navigationHelper_SaveState(obj sender,SaveStateEventArgs e)
{
e.PageState["SelectedSection"] = MainHub.SectionsInView;
}
void navigationHelper_LoadState(obj sender,LoadStateEventArgs e)
{
if (e.PageState != null)
{
var sections = e.PageState["SelectedSection"] as IList<HubSection>;
if (sections != null && sections.Any())
MainHub.ScrollToSection(sections[0]);
}
}
On the page where you use the hub, set the navigation cache mode in constructor:
this.NavigationCacheMode = NavigationCacheMode.Enabled;
or in XAML:
<Page
x:Class="App.HubPage"
....
xmlns:data="using:App.Data"
NavigationCacheMode="Enabled"
....
Better use:
this.NavigationCacheMode = NavigationCacheMode.Required;
before:
this.InitializeComponent();
And add:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
if (e.NavigationMode == NavigationMode.Back)
this.NavigationCacheMode = NavigationCacheMode.Disabled;
}
to remove cache on back navigation from page.
I have a Windows 8 app, and recently I refactored it to use a 'master page'. This means that there is one 'layout' that has a few generic components such as the header and footer. In that layout, I have a Frame. Every time I want to show a different view, I load it in the frame.
This means that my startup screen is no longer of type Frame but of type Layout, which is a LayoutAwarePage. This is how I initialize it in App.xaml.cs OnLaunched:
Layout rootFrame = Window.Current.Content as Layout;
if (rootFrame == null)
{
rootFrame = new Layout();
Here comes the problem: I have a charms flyout that contains a few items like Settings. I made a nice view (Flayouts.xaml) that contains the layout of these flyouts. The code behind for that view looks like this:
public Flyouts()
{
InitializeComponent();
SettingsPane.GetForCurrentView().CommandsRequested += Flyouts_CommandsRequested;
}
void Flyouts_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
{
// add some commands
}
And this is how you'd get this to work in your app:
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new CharmFlyoutLibrary.CharmFrame { CharmContent = new Flyouts() };
What they're doing here is assigning a Frame to 'rootFrame'. However, since I switched to a master page, I no longer have a Frame but a Layout/LayoutAwarePage type, so I can't assign the CharmFrame to it. How do I overcome this problem?
Anyone?
When navigating inside a frame the page that you navigate to is placed inside the navigate the Content property.
So if you navigate to you Layout first, then the content will be filled with your page and you can navigate to your child page's. I've placed a example below
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null) {
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
//Associate the frame with a SuspensionManager key
SuspensionManager.RegisterFrame(rootFrame, "AppFrame");
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated) {
// Restore the saved session state only when appropriate
try {
await SuspensionManager.RestoreAsync();
} catch (SuspensionManagerException) {
//Something went wrong restoring state.
//Assume there is no state and continue
}
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null) {
if (rootFrame.Navigate(typeof(Layout))) {
var secondFrame = rootFrame.Content as Layout;
if (!secondFrame.ContentFrame.Navigate(typeof(YourPage)) {
throw new Exception("Failed to create initial page");
}
}
}