Debugging hotkey collisions - a XAML with all included views? - c#

I'm maintaining a large c# XAML-based UI project which uses several embedded common or at least reused XAML controls. As in, like,
<shared:DirectionsView DataContext="{Binding DirectionsViewModel}"/>
The problem comes when I try to define hotkeys for new buttons in one UI that happen to already be in use in some included control. I can see the embedded control directly in the XAML editor, but if I want to add ALT+V as a hotkey somewhere, searching the XAML I'm editing for "_v" isn't going to find something in the DirectionsView that's hotkeyed that way.
Is there some file, maybe generated during the build process, that is the "final XAML" or otherwise represents the form with all inclusions in it? That way I'd at least have something to probe.

Is there some file, maybe generated during the build process, that is the "final XAML" or otherwise represents the form with all inclusions in it?
No, there isn't. The visual tree is composed at runtime when the XAML processor parses the BAML (the compiled XAML) and actually creates instances of the runtime classes such as your DirectionsView class.
So you will have to search through the different source files and compose your own "final" element tree "manually" I am afraid.

Related

XAML/C#: Page/Property Style Changing Efficiency

I am currently working on a WPF project, and I am at an aspect of the program where I don't know how to create the solution efficiently.
Problem:
In my program, I plan on implementing UI versions (Dark mode, Light mode, etc.). Basically just UI color preferences. However, I am unsure of the best way in which I can use the other UI features.
So far, I have set up styles for each UI preferences in the APP.XAML, based on individual properties, such as textboxes and rectangles, and put the general style within the individual pages to be shown.
The UI changes need to be kept within the same SHOWN XAML file so that events can be implemented. I believe it needs to be done by using APP.XAML (which I have already been using this). However, what would be the best way in showing the UI changes? Should I be creating a whole page style? Changing each property individually based on styles? Or is there some better way in completing the UI changes efficiently.
Thanks!
In answer to some of the questions and statements:
The standard templates (see: https://stackoverflow.com/a/45603437/563088) use Themes so that would be a logical first step to follow
It might be easier to maintain separate files with the templates and colors in resource dictionaries although templates will have to be in the Generic.xaml
Do not use events, use Commands and Bindings. If you need to use events, do not hook them up in XAML but hook them up in the OnApplyTemplate of the controls. That way templates can be swapped out and templates are no longer forced to provide specific controls/events as the OnApplyTemplate can search for a control and skip it if it isn't found.
As for switching: from experience I found it easier to define multiple color/brush/resource sets in separate files. Give these colors and brushes the same names (e.g. HighlightBrush, ButtonBorder or CheckBoxCheckGlyph). Depending on the theme you load a different resources file. the templates would simply refer to these resource names (using DynamicResource if you want to enable live switching or StaticResource for switching on restart of the window/app)

Templated Control vs Custom Control in UWP. No clear answer found online

In my UWP app, my control options are User Control and Templated Control. My understanding of a User Control is KIND OF clear at this point.
I was told that a Custom Control's style/template is only instantiated in memory once, and that this only happens at the time the control is first used. That's what I want since I know the control I am creating will be used in a ListView.
In the book, XAML Unleashed, however, the author creates his Custom Control by starting with a User Control, and then simply changing it's base class. The thing is that the control he created calls InitializeComponent(). I hear that this type of class uses more memory because it is re-instatiated for each item in the ListView.
Also, I never thought that Custom Controls used the InitializeComponent() method. I thought there was simply a call to this.DefaultStyleKey = typeof(MyClass); in the constructor. What gives? I am confused on what is what...
And last, why is the style/template of the Templated Control placed in the global Generic.xaml file, instead of its own separate file (i.e., xaml file and a code-behind file pair)? If the control is supposed to be custom and "portable", then shouldn't it be totally separate from other code? I haven't found a single article explains any of these things in detail on any level.
This is something most people get wrong so I'll try to clarify a few things for you.
Memory
The whole memory thing, it's all in the Visual Tree. When you instantiate any control, whether templated or UserControl, you will use up memory with every instance because in both cases you are creating a full copy of the visual components in the template.
The templated control will create a copy from the ControlTemplate while the UserControl parses the XAML file when InitializeComponent() is called.
Memory usage will be the same if you create 100 templated controls or 100 user controls if their content is the same.
Usage
Templated controls are best for situations where you're creating a single component, like a Button, Slider, MyStarRatingInput, etc. and you're giving the users of your control the ability to swap out the template with their own. It takes a lot more effort to do this properly than UserControls because the logic has to be template agnostic and your templates have to react properly with visual state changes.
A UserControl is best for layout or views, like forms, popups, screens, pages, etc. You will not give someone the freedom to tamper with the content of your view. You may expose a few public/dependency properties if some views are reusable in a small way, but generally they are set in stone.
Generic.xaml
I honestly don't have an answer for this. Microsoft should've allowed multiple resource dictionaries to enable cleaner partitioning of control templates. Generic.xaml is a reserved filename that referencing projects will look for as the root source of the base styles of your controls. You could reference other XAML files from Generic.xaml, but that's annoying and it bloats the root of your resource dictionary. For now, you're stuck with this method.
Recommendation
If you're sharing a control library, you would want to use templated controls as much as possible. If you're building controls, views, pages, etc for your current project and they're not meant for reuse, then use UserControls.
You can still create a UserControl in your control library if you plan on owning the template and forcing all users to accept your design.
I also recommend templated controls for items that you plan on instantiating a hundred times in a single view, like a ListView. You will see noticeable speed improvement if your template is preloaded into memory instead of parsing a XAML file on every instance.

Create WPF page fragment in Visual Studio 2015 (C#)

I am trying to develop multi-document interface for C# application (that is suprisingly hard, in Delphi it was and still is the simple task for more than two decades!!!) and it seems to me that I should use AvalonDoc framework for this https://avalondock.codeplex.com/
The essence is - all the dynamic documents will be the parts (fragments) of one (main) C# Window and there will be one XAML file - that is require by Avalon.
My intention is to create separate XAML and code-behind file for each document, is it possible to create fragments in Visual Studio 2015? E.g. such code pieces that does not inherit from Window and that can be dynamically inserted into window (e.g. as AvalonDock LayoutDocument's).
I know that VS has notion of controls and components but I am not sure - is it right practice to create entire documents (e.g. invoices, stores) as single components/controls?
Yes you can create UserControls -
They belong to the list of standard template files in Visual Studio.
A UserControl is :
1 A Xaml file for describing content.
You can design it graphically or with code editing.
2 C# or Vb.net file for codebehind = event handlers, data members, extra methods , ...
Both files make a single class during compilation thanks to the partial keyword.
Once the Usercontrol is compiled you can drag and drop it onto the surface of a Window like a standard control (e.g. button).
Usercontrols can also be instanciated through C#/Vb.Net code.
Let me know if I answer correctly - if I am complettely wrong - I Delete, or I complete if needed

Kind of live debugging possible? (Especially UI manipulation)

I would like to know if there is a way to manipulate an App's UI live while running?
I am not a designer and I have many problems sometimes regarding matching colours etc.
The next problem is that anytime I would like to change e.g. the colour of a control I have to quit the App then go to VS2012, apply my changes, build and execute it again to see simple changes.
I know that I see any changes in the designer but I have to see the resulting screen to get an impression of the whole.
Is there a way to achieve this?
Add a secret keypress while Debug flag is set, that raises a form and allows you to select controls and expose a property sheet for them. Be a bit of work to get right, and a good stick of code even using reflection. Might be better off with a storyboard type app to do your designing.
Unlike styles in WPF which can be dynamically adjusted (which made this type of run-time adjustment simple), there isn't as elegant of a solution for Windows Store apps. Ideally, you'd have all of your UI and colors, etc. defined in XAML files and not settable through other means (as it becomes a longer term maintenance issue).
I'd suggest just adding enough test data and configuration so that you can see the look and feel of the pages (with colors, etc.) at design-time. Blend and Visual Studio are now quite good at showing a very reasonable near final rendering of the elements of the application. It's generally not too difficult to do anymore.
One thing I've done in the past was to make a single page/form that contained all of the styles and controls in a large scroll viewer. Then, we set it so it was configurable to the be the first thing to run. The tweak/build cycle was pretty fast, and the results were still very manageable.

Why does C# designer-generated code (like Form1.designer.cs) play havoc with Subversion?

My workshop has recently switched to Subversion from SourceSafe, freeing us from automatic locks. This led to concurrent editing of the Forms, which is wonderful. But when multiple developers commit their changes, the code files created by the designer (all the files named TheFormName.designer.cs) cause conflicts which are very difficult to resolve.
As far as I can tell, this is because the code generated by the designer is heavily re-arranged whenever the user modifies it, no matter how little the actual change really did.
How do I make these conflicts easier to resolve?
Is there some way to tell the designer to modify the code less?
How do you, the experienced C# teams, deal with concurrent modification of a Form?
Here are some things to try:
Make things more modular. Use components like User Controls etc. to split forms into multiple, smaller physical files.
Use presentation layer design patterns like MVP to move code out of views and into standard POCO classes.
Recent versions of SVN allow you to take hard locks - use this to avoid complex merge scenarios.
Hope that helps.
I'm pretty sure there is no silver bullet for this problem as the designer stomps all over the designer.cs.
All I can suggest is to minimise the use of the designer. Personally I only hook to events in code and only use the designer only for initialisation and positioning. As such it isn't too hard to fathom differences in a changeset ("oh, someone has added a button", "oh, someone has changed how it looks slightly").
Yep, Designer's random rearranging sure is irritating. Does Microsoft use their own tools? Does Microsoft look at what they check into version-control? It boggles the mind.
Our team's "solution" is to hand-edit the Designer files after we're done editing them, to put things back to where they were, so that the text-based diff is readable, and so concurrent changes can be merged sanely. Luckily, most of Visual Studio's rearranging is simple-minded, so this works.
Sadly, we've found that this step is necessary to verify correctness -- we've found cases where Designer silently removes things that are needed, leading to broken code. So this step has to be done in order to work around whatever data-destroying bugs lurk inside. Sigh.
Since Microsoft has a poor track record of fixing its bugs, the only solution may be to improve Mono's WinForms Designer so that it's ready for prime time.
I'm not familiar with C# or the Windows Form Designer, but looking at some designer.cs files I could find online they don't have a particularly complicated structure.
What parts of it are being re-arranged? I guess it's mostly the order of the properties in the InitializeComponent() method that's jumbled up?
If that's the case, you might be able to write a simple script that re-orders those lines alphabetically, say (especially if you never edit these files manually anyway), and use that as a pre-commit hook script in Subversion.
Um, right... scratch that. The big red box at the bottom of that section says you're not supposed to modify transactions in hook scripts. But you might be able to find another way to run that script somewhere between the designer.cs file being changed and it being committed.
Edit:
Actually, given scraimer's comment on this:
Total hack, but in the worst case, just before a merge, I could sort BOTH files, and make the merge simply a line-by-line affair...
Can't you let Subversion set an external merge program? I've been using KDiff3, which can run a preprocessor command before doing diffs or merges, so you could automate that process.
It's true that the designer sometimes messes up the order of the controls in the code, which causes the file to look very different compared to a previous version. This indeed is a problem if the file is under version control.
However, I found that the designer works quite reliably even in very large forms and user-controls if you follow some rules, and in those rare case where it does not, I have a easy way to force the designer into arranging the controls in the "correct" order again.
My rules:
The comment at the top of InitializeComponent() in every .designer.cs says: do not modify the contents of this method with the code editor. Well, if you know what you're doing, then it's absolutely no problem to edit this file manually, because this is what you need to do. Just make sure you have a backup.
Typically, when you create a form or UC, you add some controls here and there and move them around until you find a nice arrangement. But in the .designer.cs file, the controls are ordered by the order of their creation, and not by your logic how they belong together.
After finishing the creation of the form or UC, I reorder both the declarations (at the bottom of the file) and instantiations of the controls and their adding to the respective parent control (both in InitializeComponent()) until they are in the order that I want them to have. This makes it much easier to find them if you have to change a property of a control in the code.
And it also makes it easier for version control, because you may easily see what part of your form or UC was changed just by seeing the place (rather towards top or bottom of the file?) of the change in a file comparison view.
But changing the order in these 2 sections does not automatically change the order of all the parametrization code that comes after the instantiation part in InitializeComponent(). This will be done when you execute the solution to the OP's problem, which is described next.
If you work with rule #2, then you need to do the same finishing work that you need to do when you encounter the problem that the OP describes:
You have to force the designer to arrange controls in the order that they have in the declaration and instantiation.
This can be done in a quite simple way (which worked for me in 99% of the cases so far):
Save all files of the form or UC
open the designer view
move one of the controls (e.g. by selecting it and hitting 1x left arrow key)
optional: look at the .designer.cs file and/or save the form or UC
move the control back to have your intended design (e.g. by hitting 1x right arrow key)
save the form or UC
The designer will rewrite the whole .designer.cs file and your controls should now be in the "correct" order.
There are rare cases where this does not help. These include DataGridViewRows in embedded DataGridViews and embedded UserControls. In these cases I additionally do similar finishing work which includes adding and removing a button:
Save all files of the form or UC
open the designer view
add a button anywhere in the form or UC
optional: look at the .designer.cs file and/or save the form or UC
remove this button again
save the form or UC
The only way I know of to truely avoid this problem when using a merge style source control system such as subversion is to hand code the forms and not use the designer. Obviously, this would not be good because hand coding these forms can take a while.
The reason this happens is because the control properties are serialized by the designer in the order they are dropped on the form. Cutting and pasting can effect this order as well as moving a control so that it has a new parent (such as moving a control on to a panel when it was previously directly on the form).
I had this problem on a large project and had to imploy a rather ugly approach - diff the designer.cs files against the check-in target revision and manually merge them using a merge tool. This isn't ideal, but it is the only way I see this working consistently with svn or another merge style source control tool.
The other option would be to use a lock approach with source control, as others have pointed out, but this comes with unpleasant side effects as well.

Categories