When creating a control in xaml, I could do two things:
Create a StackPanel, add a few TextBlocks, a Rectangle et.c
Create a templated control, and add that to my MainPage.xaml
In terms of performance (only), which one would be better? Both work fine, as I see it.
Typically, at the top of a page, I would create a kind of header panel, containing some text blocks, some visual indicator et.c. The control isn't that big, perhaps it contains 10-12 children. Usually, I just type it up directly in the page xaml, as it isn't reused anywhere. But I usually apply some kind of animation to the header panel (let's say it is part of a FeatheredTransition when loading the page).
So my question is: would there be any performance advantage (from a xaml loader/renderer/animation perspective) if I create a template control first? What's the general recommendation?
I don't think there will be any noticeable difference, so use whichever you want.
Related
I've put together a scheduling application similar in style to that found in outlook, however it can show the schedules of multiple people. I have written a user control, basically a Border with gradient filled background & TextBlock. One of these controls are added to a Canvas at a set location for every appointment. The trouble is, I will have multiple users, with multiple appointments and may need to display 1000 or so appointments at a time. Initially, it takes an absolute age to instantiate all of these objects, however, I can live with this.
Unfortunately, the big problem arises when I try to scroll through the appointments. I have a couple of buttons to scroll left and right and upon clicking these, the UserControls' Left position are moved left or right a certain number of pixels - it can take several seconds between clicking a button and repainting(I also tried with labels just to test, but it was the same).
I guess the real question here is how to implement an interface, showing hundreds of controls with adequate performance and if this isn't achievable, how would I approach such an UI.
One possible option is a TextBlock CustomControl. You can get the exact same style as you have in your usercontrol but with a somewhat faster loading time.
Without a good, minimal, complete code example that reliably reproduces the problem, it will be difficult if not impossible to completely understand the performance problem you are having, never mind provide a solution.
That said, from your description it sounds like you are really looking to present the user with some type of ItemsControl, such as ListBox or ListView (a specialization of ListBox). In an ItemsControl, you can specify an ItemTemplate that defines how each item in the list will appear; this is analogous to the UserControl you apparently are using now.
I believe it's likely it will work fine just with that change alone. I.e. define your per-item visual as a DataTemplate instead of a UserControl, and set the ItemTemplate property of e.g. your ListBox to that template, then just bind your collection of appointment objects to the ListBox.ItemsSource property.
Note that the ListBox class already defaults to using VirtualizingStackPanel in its ItemsPanel template. So you should have no performance problems at all with this approach if you use ListBox.
If you want to use a different ItemsControl or create a custom one, you may or may not find that you need to use a virtualizing panel object explicitly (such as the VirtualizingStackPanel that ListBox uses). With just 1000 items in the list, even a non-virtualized panel may be fine, but if not then even when not using ListBox, you can always specify it explicitly.
I'm trying to add a panel on two different panels in this way:
_formMain.panel3.Controls.Add(_formMain.panel1);
_formMain.panel4.Controls.Add(_formMain.panel1);
What I obtain is that panel1 is added only to panel4 and it is removed from panel3.
It seems that the latest "Add" overwrites the others "Add". Is it true?
Why? How can I add the same panel to some differents controls?
Thank you
Your title says it all:
There is only one control and it can only be in one place, read it can only have one parent.
Therefore, if you change the Parent or Add it to another Control's Controls collection, which is ecxactly the same thing, it will disappear from the previous place.. So while Add doesn't sound like it, it amounts to a Move.
If you need more controls you need to create more controls! And of course they will be different Controls, with different properties and contents..
You can have more than one control show the same content if you keep them synch'ed. One prime example with automatic synchronizing would be two DataGridviews, both with the same DataSource. For other content, like Text or Images the syn'ching is up to you!
You may think about writing a clone function, that can create a deep copy but you will still have to do the syn'ing. This may be codeable as well, depending on the details.. Or you could make it into a UserControl and add fresh instances of it.
I am somewhat new to WPF and hopefully I'm not asking for the world here but I'm looking for advice/direction on how to go about implementing something like the following.
I'd like to have my MainWindow contain N buttons. Each Button performs the same action on a different set of data (i.e. print picture 1, print picture 2, ... , print picture N). I'd like my window to automatically layout the buttons as described below:
Note how the number of buttons increases, the layout automatically adjusts in a pleasing manner. Up to 6, and then the it provides a horizontal scroll to shuffle through the buttons.
I feel like the <Grid> control might be the way to provide this but I'm lost in how to get the automatic layout tweaks short of a lot of brute fore.
Tangentially, I see the power in Data Binding in WPF and ideally the button's info (it's display text, graphic, etc.) would be automatically binded to an observable collection so that as I insert buttons into the collection, the UI automatically updates. Conversely when each button is clicked, I'd like to have a generic handler know button 5 maps to the 5th element in my collection which has all this additional info (i.e. the file name of the picture to print).
That all sounds well and good but again I'm lost a bit in the implementation.
As Allonym said, the most customizable way would be to create a new custom Panel for this.
IMHO, it may also be possible to achieve this using a UniformGrid, and tweaking it a bit with bindings and converters. That is for the layouting.
About your second question, I think using an ItemsControl is the best way. You could pass it your new Panel (or UniformGrid) as its ItemsPanel. Also, you could then create a DataTemplate with a button inside, bind its Command property to a single command (= generic Handler), with as parameter the DataContext of the DataTemplate (= the current item of the list). This part is easier than the layouting.
Does is help?
Antoine
I think you'd have to create a custom Panel class, overriding MeasureOverride and ArrangeOverride to achieve your desired layout. Check out this (very brief) tutorial.
I need to implement TabControl-like behaviour with manual (on event, on a button click for example) pages switching and having all pages designed and implemented as separate forms. A form to be incorporated (as a panel control) inside main form and replaced by another form as needed.
How to achieve this?
PS: The reason why I don't want to use TabControl instead is because there are going to be too many tabs - I'd prefer to present the list of them as a TreeView and instantiate on demand. The another reason comes from another project of mine - there I am going to implement plug-ins, where a panel inside main window will be provided by a class loaded dynamically and will be runtime-switchable.
I need to implement TabControl-like behaviour with manual (on event, on a button click for example) pages switching and having all pages designed and implemented as separate forms
May I ask why this is a requirement? It seems like the logical approach would be to create a set of UserControls. You can place a UserControl in a form, and you can place a UserControl in a tab. You get modularity without the headache of implementing a very odd requirement which is a use case that the API developers obviously did not think was valid. I just can't think of a good reason to take the route you have suggested.
I did similar thing once, and for that reason, I have ReplaceControl method, which I paste below:
static public void ReplaceControl(Control ToReplace, Form ReplaceWith) {
ReplaceWith.TopLevel=false;
ReplaceWith.FormBorderStyle=FormBorderStyle.None;
ReplaceWith.Show();
ReplaceWith.Anchor=ToReplace.Anchor;
ReplaceWith.Dock=ToReplace.Dock;
ReplaceWith.Font=ToReplace.Font;
ReplaceWith.Size=ToReplace.Size;
ReplaceWith.Location=ToReplace.Location;
ToReplace.Parent.Controls.Add(ReplaceWith);
ToReplace.Visible=false;
}
Only thing left to do is to create some control manually on the form, as the placeholder for your Form. Use label, for example.
You could do this with an MDIForm as the main form, and then plain-old Forms as the separate forms. Or you could encapsulate each element's functionality as a UserControl which you can then swap out on your form in code.
The advantage of encapsulating your UI elements as UserControls is that if, for whatever reason, you need them to become forms in your application, you can just drop the UserControl on a form.
Update: Since you want to use a TreeView to select what the user is looking at, you definitely want to do this as a bunch of UserControls. The layout is simple: TreeView on the left, and whichever control is active on the right.
There's no need to justify not using a TabControl - tabs are the worst UI element in history.
I'm trying to learn WPF and was thinking about creating a simple IRC client. The most complicated part is to create the chat log. I want it to look more or less like the one in mIRC:
or irssi:
The important parts are that the text should be selectable, lines should wrap and it should be able to handle quite large logs.
The alternatives that I can come up with are:
StackPanel inside a ScrollViewer where each line is a row
ListView, since that seems more suitable for dynamic content/data binding.
Create an own control that does the rendering on its own.
Is there any WPF guru out there that has some ideas on which direction to take and where to start?
I suggest you start with a good object model independent of the UI, and then try a multi-line TextBox or a RichTextBox.
Whether these will suffice will depend on exactly how long you want the log to be able to get. If you run into performance issues, you may need to look at virtualization.
First of all, you should consider if you want to select only entire row (like in a listbox), or if you want to select certain characters from a row (like in a textbox).
In the first case, I think a ListView or even a ListBox should be enough, both of them support virtualization when bound to collection and there should be no problem with huge amounts of data. A stack panel inside a ScrollViewer is a little bit like reinventing the wheel for this case and creating a new control is not a very inspired approach in my opinion (as the functionality you want can be achieved with the existing controls, in WPF).
In the second case, if you want to select some text inside of a line, or if you want word wrapping for your longest lines in the log and want to select individual parts of the wrapped lines, then you need to use a control more oriented on displaying text. Kent already suggested a RichTextBox, I would add AvalonEdit control or even the WebBrowser control in which you directly modify its HTMLDocument.
I would suggest to use RichTextBox too, and store items in a log file or database, if you run into performance issues.
Another solution is to use the WPF WebBrowser control and modifiy its HTML content with:
webBrowser.NavigateToString("<HTML><H2><B>This page comes using String</B><P></P></H2></HTML>");
More information about using WebBrowser control