Where does the look of wpf come from? - c#

I just read the book on WPF from Thomas Claudius Huber. He stated, that all WPF controls are "lookless". They just get their look (and visual tree) from their ControlTemplate. That raises one question: Where does the look of WPF come from?
I mean: the Button has a ControlTemplate with some Borders and a ContentPresenter. Where do these two (Border and ContentPresenter) get their look from?
I already googled and found, that Border is a Decorator and sets its look in the OnRender-Method.
Is that the bottom line? Do all other elements which don't have a ControlTemplate define their look in the OnRender-Method?

Short answer: Yes. All visual elements that are not Controls and have a "look", define said look in their UIElement.OnRender method override.
Long answer: Controls don't use the OnRender method to define their looks. Instead, their "looks" are defined in Styles and Templates. When no Style or Template is defined explicitly in an application, WPF Controls simply use their default Styles and Templates from the current system Theme (for more info on Themes, check this MSDN article).
Let's just say that the Framework has its own Resource Dictionaries with default Styles for all built-in controls. For instance, here is the default ControlTemplate of the ComboBox: ComboBox Styles and Templates
That being said, there are several visual components that have their looks defined through code, usually through the OnRender override. They're not Controls; they're Decorators, Shapes and things like that. Things that do have a "look": Border, Rectangle, etc. But in the end, all Controls have look thanks to these elements because all ControlTemplates are made up of either these elements, or other Controls.
TextBlock, as Run, FlowDocument and other similar elements, are special elements created specifically for text renderization. They fall into a similar category than Shapes or Decorators, except they specialize on text rather than graphics. TextBlock, for instance, is not a Control, and defines its look on its OnRender method. Label, on the other hand, IS a Control; but if you check its Template, you'll see it ends up using a TextBlock to show the text.
There are other elements (like ContentPresenter, ItemsPresenter) that have no look whatsoever, not implicit, not by default, not by Styles or Templates. These are logic elements, that define the structure of the view. ContentPresenter, for instance, grabs the Content and ContentTemplate properties of a ContentControl, and makes sure that said Template is correctly rendered and bound to said data, so to speak. But they have no visual representation of their own.
Oh, and I almost forgot about Panels. Panels are not Controls, either, and they do have a look of their own. But similarly to Presenters, they're also logic elements that define how the other visual elements are visualized. More specifically, their layout.

Related

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.

Contentcontrol or dockpanel for navigation wpf

I use a Contentcontrol to show the user controls of the program, Now there is a problem for me to close the user controls After searching, I found an example that The user controls is loaded on a DockPanel
Now my questions:
What is the difference between these two controls? (Dockpanel vs ContentControl)
Is it okay to use this control(dockpanel) Instead of Contentcontrol to display application user controls?
Is there a similar code for Contentcontrol?
ucChild ChildWindow = new ucChild();
ChildWindow.ParentControl = this.UIPanel;
UIPanel.Children.Clear();
UIPanel.Children.Add(ChildWindow);
Standard disclaimer for people coding WPF like it is WinForms: First off; direct UI manipulation like this is a bad idea. You should
be modifying a view model and allowing the binding system to update
the UI. Use the MVVM pattern; WPF will work for you instead of
against you
To your actual questions:
Everything. I mean; they both inherit from FrameworkElement but that's about it in terms of commonality.
A DockPanel is as the name suggests, a Panel. That is; it controls the layout and sizing of one or more child elements. Specifically, DockPanel is good at situations like the following: you want an element to use up a full column of width, then another span the top (except for the previous element) and have the last element fill the remaining space.
A ContentControl is basically a placeholder, its purpose is to expose a settable (and most importantly, bindable) Content property that you can stuff another control into. Even better; you can put an actual object there and use a DataTemplate to control the display (this approach would conform to MVVM).
You can't really replace one with the other, see above
No. ContentControl is not a Panel and so does not have the Children property.

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.

How to make message entry/list/view in C#

He I am a beginner to C# and I am working on a reaction manager plug-in for some bigger project. (Yes I am a intern)
Now I just can't find a way to create a view similar to this:
My full design:
How to realize this design? I cant find any default templates in the devexpress which are suitable for this. I come from php and in php I can use html. I am a beginner to C# and I don't have any clue on how t do this. Do I have to use canvas to literally draw this? OR is there a standard template I can use for this purpose.
You have many comment boxes that contain the same layout - a label comment text, author name, date, etc. There is no control that lays things out like that, you will have to make your own custom control (Project->Add User Control). This control will be a composite control - ie made up of other controls. Probably a label for each text field (comment, author, date, etc) laid out in the right places. Maybe call it CommentBox or something.
Then in the main form you now have available CommentBox controls which you can add to the form. Create a panel to put them in so you have many CommentBox controls in the panel, one for each comment (or maybe add them at runtime).
Now in WPF it's slightly easier because there is a StackPanel control that you can simply add controls to and it automatically arranges them vertically one beneath another in a stacked list. In fact your use case is exactly fitting what a StackPanel is for.
In WinForms there is no StackPanel, but you can use a normal Panel control*. It's just you'll have to position the CommentBox controls manually one beneath another. You will also need to set the AutoScroll property to true to turn on the vertical scroll bar if the content doesn't fit the view.
*or there's apparently an alternative How can I get a StackPanel-like layout in WinForms

What to extend for a new custom control?

Some people suggest to just extend Panel but I also know about UserControl that sounds like something I should extend to make my own control.
Panel vs. UserControl vs. Control vs. another_alternative
// inheritance depth:
Control
Panel : ScrollableControl : Control
UserControl : ContainerControl : ScrollableControl : Control
All I need is a rectangle to draw and full WinApi ability (Handle, WndProc etc.). But I want to avoid all the extras that might come into the play. I want to use my custom controls to add them to standard forms. No extreme actions.
On the other hand UserControl extends ContainerControl that might have functionality I want (I'm not sure).
I inherited from Control for an OpenGL box and some other simple controls. They work fine so far. I haven't noticed any functionality-loss. Does something speak against Control ? (in case I don't require any extra functionality)
I think the unofficial and accepted "standard" is to just inherit from UserControl. At least that's what I've seen everywhere else. That does not make it the right thing though!
On the other hand, I think you also may be too concerned about the "right thing" to do here. To me, this is almost similar to premature optimization. You want to make sure that you spend your resources wisely.
Also keep in mind that things like this can always be changed later.
If you're concerned for a reason, I would definitely pick the simplest of the controls with the lowest inheritance depth.
Mostly UserControl is the best class to inherit from. Another option could be to inherit from the class that we want to customize.
In your case, Panel should be the best class to inherit from as it is the simplest control class that would serve your requirements.
Panel would be ideal here because you are not defining a layout for the control. Nor does it need a ControlTemplate. Custom rendering schemes generally come with the recommendation to use Panel. While Control is the simplest 'layout' element you can get at, Panel has the ability to host child controls should you need to later. Perfect!
There is a description of what exactly differentiates UserControl from ContentControl in the "Pro WPF" book, which gives more information than MSDN. Here is a direct link to the section:
http://books.google.ca/books?id=znAVMHNSen0C&pg=PA518&lpg=PA518&dq=%22taking+a+closer+look+at+user+controls%22&source=bl&ots=DjZT-9JCQd&sig=R4MoAzW72PaHvqgZjxPnkkJRs6c&hl=en&sa=X&ei=OdQIUrPgDeTYyAGl6oHYAQ&ved=0CC8Q6AEwAQ#v=onepage&q=%22taking%20a%20closer%20look%20at%20user%20controls%22&f=false
The most interesting difference is how it handles routed events. All events raised by contained elements have their Source reset to the UserControl itself.
I think the conceptual difference is that a ContentControl "contains" its content, while a UserControl's content is "part of" the UserControl. Thus a ContentControl is a distinct element (is focusable / a tab stop) whose contents are handled separately; and setting the content of a UserControl is part of its design process, whose elements are handled directly in the UserControl's code-behind.
So, my rules are:
If the user is meant to inherit it and handle content in code-behind, inherit UserControl.
If it's meant to be used as-is and given arbitrary content, inherit ContentControl.
If it defines its own content, and doesn't have a placeholder for arbitrary content, inherit Control and set its Template.
If you just want a rendering surface, I don't think you would need a Control. You can use an ImageSource for this, like InteropBitmap or D3DImage, which can be attached to an ImageBrush. For example, it could be used in a stand-alone rectangle:
<Rectangle>
<Rectangle.Fill>
<ImageBrush>
<ImageBrush.ImageSource>
<!-- ImageSource here -->
</ImageBrush.ImageSource>
</ImageBrush>
</Rectangle.Fill>
<Rectangle>
Or anywhere else that accepts a Brush, including the Background of another control.

Categories

Resources