Navigation menu for a standalone WPF application - c#

Im just starting out with wpf (in blend 4) and i would like to create an application that has a side menu for changing the content. What i am looking for is something like in word 2010 under the file menu. if you click the menu on the left side the content on the right side changes accordingly. i have read articles about nesting a page.xaml into a frame and change the frames navigation source to each page. Is this right? When i do that a navigation bar appears at the top. I can get rid of that easy but it seems like i am taking the wrong path at what i want to achieve.
Thanks in advance.

Just to chime in on this, both the TabControl and the Frame-based solutions are somewhat like the extremes of a spectrum. The tab control effects a very close coupling between the tab state and the displayed UI (e.g., you might find it difficult to change to a dialog for which there is no explicit tab item), whereas the frame enables relatively loose coupling, but might be overkill for this scenario, as it aims to support full-blown linear navigation with a history/page stack. (Prism, for example, offers a similar mechanism through its "regions" concept.)
A middle ground could be to have a main "window frame" UI with a placeholder element, and have your individual "pages" derive from UserControl, making them regular UI elements. To switch to a specific page in your UI, you would instantiate (through code or XAML resources) the corresponding user control, and set it as the Content property of the aforementioned placeholder element. (This is basically the same mechanism you mentioned for VB, where you hide/show subforms.)
So there's a range of options to choose from, depending on the actual constraints of your scenario.

The simplest code to do that is creating a TabControl with TabStripPlacement="Left". For example :
<TabControl TabStripPlacement="Left">
<TabItem Header="Tab1" />
<TabItem Header="Tab2" />
<TabItem Header="Tab3" />
</TabControl>
You can apply Styles to further change UI, colors and look & feel.

Related

(WPF) Popup with a TabItem Layout

I currently have an application that uses a ToggleButton/Popup feature and it all works as expected, but I wanted to see if there's a way (either through control templates or custom controls) that allows the toggle button to be included as part of the popup window.
The effect I'm going for is similar to the standard TabControl/TabItem layout but instead the ToggleButton would replace the header of the TabItem and the Popup would serve as it's content.
In the end, I want to have the Popup window display to the immediate right side of the ToggleButton and have one continuous border that wraps around the outside edges of the ToggleButton and the outside edges of the Popup window with no border inbetween. The final appearance would show no separation between the two controls, and the user would perceive the ToggleButton and the Popup as a single control object.
I was thinking it might be possible to edit a template of a standard TabItem and have it's content property display as a popup, but haven't tried it yet.
Let me know if you think this is the way to go or if there's any other potential solutions. Thanks.
Almost everything in WPF can be done in multiple ways. The same is true with your goal.
If you plan on reusing this control in multiple places, I would suggest building it as a custom control. I build custom controls and UI libraries for a living, so I am a bit biased.
I would build a custom control that inherits from HeaderedContentControl. The Header property is the content of your ToggleButton, and the Content property would be the content of your Popup. Since you own the ControlTemplate and code, you can make it look and function exactly how you need it to with no compromises.

How to extend text selection across text blocks in a UWP app

My app has a bunch of paragraphs which are compared together. This is implemented using a generic ItemsRepeater that creates as many Grid elements as there are paragraphs. Inside each grid is a TextBlock with the paragraph number, and a RichTextBlock that contains the paragraph. The hierarchy is therefore like this:
<ItemsRepeater>
<Grid>
<TextBlock />
<RichTextBlock></RichTextBlock/>
</Grid>
<Grid>
...
</Grid>
<Grid>
...
</Grid>
</ItemsRepeater>
This results in a text selection as follows:
Only one RichTextBlock can be selected at a time. However, I would like to allow text selection of all paragraphs of the ItemsRepeater. How is that possible?
Edit
I'm open to other approaches. I've tried manually filling in a StackPanel or RichTextBlock with items. That's not a problem. However, because the numbered paragraphs need to align, I need to be able to set their height to match each other. From what I can find, only elements that derive from FrameworkElement have the ActualHeight and Height properties I need for that. However, FrameworkElements like TextBlock and RichTextBlock also do not allow multiple selection, which is the problem I'm trying to solve in the first place. Someone posted a response to a similar question about WPF, but it uses a strange solution I don't think applies.
So the question could also be framed as: how is it possible to find and set the height of a Run within a TextBlock or RichTextBlock? Using that idea, it was impossible to get/set the run height inside a paragraph. I'm not bound to using ItemsRepeater, but that has also not yielded a useful result. I'm seeking to avoid resorting to HTML/Javascript for this.
UWP does not expose enough APIs for you to do that. I have worked on a similar issue with RichEditBox on UWP and there is no good solution that I have found. But if you really want to, there are two main approaches to achieve that:
Implementing the selection yourself by sniffing the mouse events and render the selection on top of the controls. There are so many corner cases, specially if you want to have a proper accessibility tree for the control that you are building.
Alternatively, you can create a WinRT C++ project where you would have access to more APIs, build a control and render it onto a canvas that is created with your C#/Xaml app.
The good news is that you are not permitting people to edit (RichTextEdit) and it is just view (RichTextBlock) so you do not have to worry about the automatic corrections, IME, Url detection, etc.
Edit: Originally I mentioned WinRT C++, but I meant C++/CX. It might work with WinRT too, but I have not tried.

UserControl to avoid duplicating menu on every Page

My question is as follows: my app needs to show a "Hamburger" menu in the left side, while the content right of it changes depending on the context. My initial idea was to implement it with Frames inside different Pages. I learned that the Frame itself is a reference to rootFrame so there's really no need for nested Frames to get navigation going.
However, to get the Hamburger menu on all Pages I would need to include them somehow. Is there a possibility to avoid duplicating the XAML code in every Page?
Looking into this I found UserControl. The docs are a bit hard to understand for me. Say I implemented a UserControl in XAML and named a Button in it via x:Name="HamburgerButton". Then, in myMainPage` I put something like this:
<Grid x:Name="MyGrid">
<controls:MyControl />
</Grid>
The Button in the UserControl XAML has a Click event in the code behind. How do I extend / customize the implementation of it in the MainPage that uses it? I guess I don't understand the relationships between them. Also the ContentPresenter is over my head at this moment.
You don't need the ContentPresenter. That's for when you create your own templates. Your MainView should contain your Menu buttons and a ContentControl. When a user clicks one of the buttons, you exchange the Content property of the ContentControl: For each menu item you can create an extra UserControl, one of which is always set to the ContentControl. For example, when the user clicks "Menu X" then you set the Content property of your ContentControl to UserControlX that contains all the context-related things. When the user clicks "Button Y" ... you get the idea.
You can do all this from the code-behind file of your main view. In the long run, you'll probably want to look into the MVVM pattern and bind your ContentPresenter to a property of your MainView's view model - and your buttons potentially to ICommands. But it will also work via the code-behind method.

Change parent of a control in a size trigger in UWP

I'm creating a Windows 10 Universal app, there are two panels in my main page.
In tablet/desktop mode, both are visible at the same time (just two simple Grids, one fills the left side and the other one fills the right side)
However, in phone mode, there's a pivot and user can swipe between panels.
(I could use SplitView and hamburger menus which work easily in both Tablet/Desktop and Phone modes, but a pivot makes more sense in my case)
So, What I currently did is, I have two instances of each panel. PhonePanel1 and PhonePanel2 are two grids inside two pages of my pivot control, and TabletPanel1 and TabletPanel2 are two grids which can be shown side by side. and I use AdaptiveTriggers to detect page width and switch between these two view methods.
However, having two instances of each panel is not a good approach, because those are showing basically the same content.
Is there any better approach to do this? Maybe changing Grid's parent when triggers are changing view mode? or something better?
The only way to change the parent that I can think of is to write some code behind that will render them in the new location. A suitable solution may be to defer the loading of the controls until they are needed.
x:DeferLoadStrategy=”Lazy“
If you add this property to your controls that are duplicated, they will only be loaded when required. So on a phone the PC/Tablet view should never be loaded, unless the user is running in Continuum on an external display.
On a PC you may still end up with both loaded (If the user resizes the window) - On a PC there are usually more resources so it's less of a problem there in most cases.
I looked into the code behind approach to move the controls to a different parent and I think honestly it's premature to do that when it might not even improve performance.
I have gone for the Defer Load Strategy property and found performance to be fine, and it requires very little code. My duplicate controls are sharing the same ViewModel so I pretty much just added the property to ensure resources are only used when essential.
There is nothing wrong in your approach. To reduce memory usage, when adaptive trigger happens for example on the phone, set TabletPanel1 and TabletPanel2 visibility to collapsed.
If all panels use the same datacontext then leave it as is, if not set datacontext for collapsed controls to null.
You could create each of your panels as user controls then you've only need to define the contents once but each control could be included in each of the layouts you want.

Edit the style/template of a control created from code-behind

I'm styling WPF's Calendar control and I've reached a point in XAML where there's a grid with no elements in it, just divided by rows and columns where the day numbers are.
I've snooped and decompiled (void PopulateGrids()) and have learned that in code-behind the Calendar is creating CalendarDayButton and feeding it to the grid.
I need to change the style/theme in-order to change the colors (of those CalendarDayButton) and I'm not sure how to do that.
I've tried applying a style to all CalendarDayButton in said grid, but that didn't work.
Any suggestions?
P.S. I'd rather stay away from code-behind because what I'm working on is a style in a resource-dictionary and not a user-control.
Go to the Microsoft page for Calendar Styles and Templates, copy the style code into your resources block and make changes as needed. If you need to create additional properties for settings etc then you can do so with an attached property, that way you don't need to create a new calandar control. If you're having difficulty figuring out which parts of the template correspond to things you're seeing on-screen then put a breakpoint in your code somewhere, add the calandar control variable name to your watch window and click on the little magnifying glass to bring up the WPF visualizer...that will let you traverse the visual tree and visually see which part of the control each section is rendering.

Categories

Resources