I'm using Template 10 in my UWP application. However I need to Enable/Disable the hamburger buttons according to my conditions.
I'm setting IsFullScreen property to true initially because I want to show the hamburger menu after user logs in the application.
Because the Shell page is loaded initially then at runtime if I create a new instance of it then the application is running on full screen and I'm unable to see the Menu.
Thanks for the help in advance.
Accessing Shell page instance
You will first need to be able to access the Shell page instance. You can do this in two ways. If you know, there will always be a single instance, you can add a static property pointing to it like this:
public static Shell Instance { get; private set; }
And set the instance in the constructor:
public Shell()
{
//InitializeComponent(), etc....
Instance = this;
}
Now from anywhere, you can use Shell.Instance to access it. If you could theoretically have multiple windows, you can access the instance of current Shell using Windows.Current.Content. If you used the Template 10 Hamburger template, you would do:
var dialog = (ModalDialog)Window.Current.Content;
var shell = (Shell)dialog.Content;
Disabling/enabling
The items in HamburgerMenu control are of type HamburgerButtonInfo and have an IsEnabled property which you can use for enabling/disabling. If you add a x:Name="Menu" to the HamburgerMenu control, you can then write a enabling method like this:
public void SetMenuEnabled(bool enable)
{
foreach (var primaryButton in Menu.PrimaryButtons)
{
primaryButton.IsEnabled = false;
}
foreach (var secondaryButton in Menu.SecondaryButtons)
{
secondaryButton.IsEnabled = false;
}
}
You can put this method in the Shell page and call it via Shell.Instance.SetMenuEnabled(false) to disable and Shell.Instance.SetMenuEnabled(true) to enable all buttons.
Related
First part of my question
I am creating a UWP app which uses the NavigationView class and need a little help as to building a good approach as to how I manage control creation in code behind (not in a markup language).
I decided as opposed to adding controls in the markup language xaml that I would create a list of controls in C# and add these control as part of my NavView_Loaded method.
I understand there are benefits to simply working with xaml to create the UI. However, I intend to have various different circumstances under which controls are visible or collapsed and I find it easier to maintain the status of controls by working in code behind or in C# using my mainpage class.
Currently, I have something like the following
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
public ObservableCollection<NavigationViewItem> SetNavViewItems()
{
var navitems = new ObservableCollection<NavigationViewItem>
{
new NavigationViewItem()
{
Content = "Home",
Icon = new SymbolIcon(Symbol.Home),
Tag = "home",
Visibility = Visibility.Visible,
},
new NavigationViewItem()
{
Content = "Documents",
Icon = new SymbolIcon(Symbol.Document),
Tag = "documents",
Visibility = Visibility.Visible,
},
new NavigationViewItem()
{
Content = "Library",
Icon = new SymbolIcon(Symbol.Library),
Tag = "library",
Visibility = Visibility.Visible,
}
};
return navitemsHome;
}
private void NavView_Loaded(object sender, RoutedEventArgs e)
{
navitems = SetNavViewItems();
foreach (var navitem in navitems)
{
NavView.MenuItems.Add(navitem);
}
}
}
As I understand it, in this example I have used a strongly typed collection in order to contain a collection of NavigationViewItem's. My issue here is that I wish to create a collection, list or arraylist of various types of controls (i.e. NavigationViewItemHeader, NavigationViewItem, NavigationViewList, NavigationViewItemSeparator).... and I'm not sure what is most appropriate; a list, a collection (weakly typed), an arraylist or if there is a better option.
To round out my explanation.
I then have a separate list (of strings) which contains all of the navigation item tags which I use to test conditions and set whether a corresponding control is visible or not.
Second part of my question
One other UI control I'm struggling with which may or may not be fully implemented as part of the NavigationView class, is expanding an Item or Header to display a list of sub items. My current understanding is that NavigationViewItem is the most appropriate control to use as the main heading/item. The sub items should be using the NavigationViewList. I can then write a method for setting the visibility of the NavigationViewList controls which is triggered when the user clicks on the corresponding NavigationViewItem.
Third and final part
Whenever I create a control in my NavigationView (i.e. a stack panel), it appears to automatically create a NavigationViewItem with the content stack panel which has the default style (i.e. height). I expect that this is intended and any control created in the NavigationView inherets from the NavigationViewBase. Frustratingly I seem to have difficult displaying multiple rows of a stack panel or grid which inherets from NavigationViewBase. Can anyone shed some light? Is this in my imgaination or is there something important to understand when creating a control in the NavigationView class.
Any help much appreciated!!!
Thanks!
This may be a very simple question, so my apologies.
My problem here is that I want to build a Multilingual WPF App using C#, but I don't know how to make my different Page elements inherit the same method which makes my MainWindow translate to different languages. The app is done, I'm just translating it to English (My native language is Spanish).
I'm using Resource files to translate it.
Code for the language translation:
private void Languages_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//This is the combobox in which you select the language to display the app in
Set_Language();
}
//This is the method to invoke the Resource Manager and all the stuff from the resource file.
private void Set_Language()
{
if (!boolInit)
{
strLanguage = "LeitProjekteV2._0.Languages." + ((ComboBoxItem)LanguageSel.SelectedItem).Name.ToString();
ResourceManager LocRm = new ResourceManager(strLanguage, typeof(MainWindow).Assembly);
//Menu buttons
lblMenu.Content = LocRm.GetString("strMainMenu"); //The names inside the "" are the names of the resource in the Resource file which, depending on the language selected(Spanish, English and German)
//Change the text of whatever I choose; in this case, a Label named 'lblMenu'
MapButt.Content = LocRm.GetString("strMapButt");
BuscButt.Content = LocRm.GetString("strBusButt");
AgeButt.Content = LocRm.GetString("strAgeButt");
ComButt.Content = LocRm.GetString("strComButt");
InfButt.Content = LocRm.GetString("strInfButt");
LoginButt.Header = LocRm.GetString("strLoginButt");
RegisterButt.Header = LocRm.GetString("strRegisterButt");
ContacButt.Header = LocRm.GetString("strContacButt");
MasButt.Header = LocRm.GetString("strMoreButt");
//Here go the names of everything the Pages contain that I want to translate, just like above
//Have no idea how to inherit this method to all the pages
}
}
Now, I have several pages embedded in the same MainWindow.xaml, so that you click the button "Map", a Frame changes it's content to a Page named Map.xaml, and so on for other buttons.
But how do I make those Pages also translate?
Since the Set_Language() method takes the string value of the Combobox in order to select the correct Resource File, I don't want to create one combobox for every Page that I have, albeit that would eliminate my problem.
Any help? Sorry for the horrible way of asking, I'm still getting the hint here.
Thanks.
Use the below:
var wnd = Window.GetWindow(this); //get current window
Cast it to your window class and expose your language as a public property
Use your page to get the property by finding the current window
You may create a parent page class that do the above, and inheriting it for all your pages so you dont repeat code
I can see the difficulty you are facing is that you can't find a way to share the combobox across the main window and the pages hosted in the frame.
You can set a global variable that is accessible from the whole application, a good place is in application settings. Then when you make a selection with the Combobox, you just update the selected value to that variable.
Then call each page's Set_Language() method when they are being loaded into the Frame. In the Set_Language() method of each page, you can query what is been set to the variable stored in the application settings.
If you want to quick solution, create a static class to hold the selected language is also OK.
static class UserSelections
{
public static string Language { get; set; }
}
I'm using the fantastic Template10 for my Universal App and MVVM..
What I'm trying to do is to hide and show the hamburger button declared in the Shell.xaml file from a different view. The ideal solution would be something like.. If I don't say nothing, then show the hamburger button, otherwise, hide the hamburger button..
Let's suppose I have the MainPage and when I click an item in the list I navigate to the DetailsPage, in the constructor I send a message or set a property that infor the ShellView to hide the Hamburger button.
What's the best practice for doing that?
Messenger can be a possibilty imho but I'm not sure that is the best solution..
If you are using Template10 then in the Shell.xaml.cs you should have this:
public static Shell Instance { get; set; }
public static HamburgerMenu HamburgerMenu { get { return Instance.MyHamburgerMenu; } }
public Shell()
{
Instance = this;
this.InitializeComponent();
}
Which will allow you to access the shell instance from anywhere from you app, and with code:
var h = Shell.HamburgerMenu;
h.HamburgerButtonVisibility = MyVisibilityParam;
you can acces the visibility of the HamburgerButton, MyVisibilityparam here can be Visibility.Collapsed or Visibility.Visible
I think Messenger will fit well in here, fire it from other Views to update the button.
I have a usercontrol where I want a property that can list all the other instances of the same usercontrols in the Windows Form.
Eg. I have a simple usercontrol (sidebarbutton). I drag-drop 2 instances of it in a UserForm. Now I want a property (in the usercontrol itself) that can list both of them.
I have written this property. However, when used in Property Browser Window of Visual Studio, it allows me to add new instances of sidebarButton control.
private List<SidebarButton> _sidebarButtons;
[Browsable(true), EditorBrowsable(EditorBrowsableState.Always), Category("Roshan")]
public List<SidebarButton> SidebarButtons
{
get { return this._sidebarButtons; }
set { this._sidebarButtons = value; }
}
How to add the 2 instances that I drag-droped in the form in this property.
I know the property needs to be modified but don't have a proper direction to take. Please HELP me.
One way of doing this could be that upon addition of the user control to the form, the user control notifies all other user controls of that type that it now exists. Your user control can implement an interface like so:
public interface INotifiable
{
public void AddToList(INotifiable newButton);
}
When the user control is added to the form you iterate through all the controls and check whether they implement this interface. If they do you call the AddToList method and pass the newly added control to it.
I have a form. This form has a user control. This user control has a panel and a context menu. The context menu is not attached to the panel. There are other controls that are dynamically created and added to this panel. One of those controls is a button. When you click this button, I set the contextmenustrip property to my context menu.
My problem is that I need to read the items in that context menu prior to there being the opportunity to attach the context menu to the button.
Each time a form is loaded, I iterate though all the child controls of the form. If a control has children, I iterate through those, and so on... I can't seem to get at the context menu that is unassigned so to speak. It has not been attached to any control so it does not appear to be a child control of any controls on the form.
myConectMenu is never added to the user conrol like this.Controls.Add(myConectMenu). How can that context menu not be nested in the forms control collection? How can I get at that context menu?
Here is the designer code:
private System.Windows.Forms.ContextMenuStrip myContextMenu;
void InitializeComponent()
{
this.myContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
this.myContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.myToolStripMenuItem1,
this.myToolStripMenuItem2});
this.myContextMenu.Name = "myContextMenu";
this.myContextMenu.Size = new System.Drawing.Size(158, 92);
}
Update
The control iteration happens in a base class from which all forms in my application derive.
There is a private components object that the myContextMenu is added to. I imagine this is there so you can see the context menu in design view when it's not attached to a control. Perhaps I could leverage this?
private System.ComponentModel.IContainer components = null;
this.myContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
As you correctly observed, myContextMenu is not added to the Controls connection. Control has ContextMenuStrip property which you should check.
public void FindContextMenuStrip(Control input)
{
foreach(Control control in input.Controls)
{
if(control.ContextMenuStrip != null)
DoSomethingWithContextMenuStrip(control.ContextMenuStrip)
if(control.Controls.Count > 0)
FindContextMenuStrip(control);
}
}
Put relevant code in DoSomethingWithContextMenuStrip method.
EDIT:
I saw your comment where you specified what you wanted to do with ContextMenuStrip.
How about creating a method in Base class which takes user details and creates a context menu strip?
public ContextMenuStrip GetContextMenuStripForUser(User user)
{
//code to create context menu strip, with only those items enabled for which user has access.
}
In your final form, use this method to get ContextMenuStrip.
Create a custom contextmenu (SecureContextMenu in my case) that derives from contextmenu. Implement the open event and iterate through the items collection disabling the items that are not authorized.
Be sure to create a HasBeenOpened property and set it to true the first time the open event fires so that you don't have to keep checking the same controls every time the context menu is opened.
Use the SecureContextMenu everywhere you want context menu items checked against the list of authorized items.
It's a component and not a control attached to the form. Compare it to another form: you can manually .Show() a form from another form, but neither of them will show in in each other's .Control collection. Well, maybe that analogy wasn't the best... :s