I am using Autofac with my WPF project.
At design time for some controls, I set the data context of these controls to a designer-specific view model. This view model then injects some services in through its constructor.
That's all fine. But how can I manage lifetime scoping for this? Is there any way to hook up to an event and dispose my Autofac container when the design-time phase is done?
You've said in comments:
The problem is that some of my services (for instance a hotkey service) is using the RegisterHotkey API. For that service, it's important that it is unregistered when Visual Studio is done rendering my design.
In general, those should not even get registered first when your component is in DesignTime. Designtime if for previewing the layout and inspecting view modes/states, not really for testing (though it's very tempting sometimes).
When in designtime, all interactivity of the component should be disabled. VisualStudio tries to do that, you will notice that many interactivity events/triggers are not invoked or passed to your component. However, it sometimes fails badly at this, like in case of Popups (and therefore Dropdowns, Comboboxes, etc) you can sometimes force to actually open in design-time and it yields very strange/unstable/otsafe results.
This is why you shouldn't fully trust VS and the design-time mode to "just work". You probably already know well that poorly written component can, in desing-mode, try for example to connect to a database. It shouldn't happen. Usually.
I'd say, refactor that hotkey-registering bits out into some service and stub/nullify/disable it when you detect designtime mode.
I doubt they worked in designtime, but if you needed these hotkeys to flip some switches in VM on and off, or to invoke some behavior, bind that switches or behavior to a few new properties, and instead of pressing hotkeys, set them in the designer or by designtimedata to check the effect.
Just FYI - I never researched this for WPF/XAML, but for WinForms, each component could come with a special "designer" component. VisualStudio used that 'designer' component for preparing, mantaining, rendering, editing and serializing the edited component. You could actually write a designer for your custom control, and that designer could display extra windows with custom editors, and so on. Toolkits like DevExpress heavily relied on that. I'm not sure if that there is a similar framework for XAML components. I doubt it's the same, but there may be some similar concepts kept. Anyways, I wouldn't dig into this on your place, not for such things. It's not worth it unless you really want to start extending the Designer with your custom plugins.
Related
I'm writing a program to implement COM component in C#. This component provides a UI component too. In the interest of making it easy to implement future additions to the component, I decided to write the UI in Xaml using WPF and wrapping it in an ElementHost control to provide the handle back to to the COM consumer.
Here's where this gets interesting. The element is being hosted in a win32 tab control. The first time the tab is selected, it loads fine. Switching to another tab and coming back causes it to not draw the component correctly. If I move the mouse through it, it'll draw the TextBox elements, but it'll never redraw the whole UserComponent.
I've tried every possible solution I've seen suggested, from changing the height/width values of the component to putting the HwndTarget in SoftwareOnly rendering mode.
I'm not sure what to try at this point, so suggestions are welcome. I'd really like to do this without using Windows Forms as the future maintainers of this aren't the best programmers and it's a lot easier to tell them to write up a Xaml file with data bindings than manually lay out a form and set the values in the code-behind.
Haven't met such problem yet.
Try to force refresh or focus (methods) to the hosting wrapper or HwndSource when switching to the hosting tab.
I've a question more about 'Good Programming Practices'.
I have just started a really big project. I'm using WebGui (long story short.. it is WinForms in web) - but it's not important.
I'm creating milions of forms with milions of controls like TextBox, NumericUpDown, DateTimePicker and etc. It might happen, that I will have to change something in behavior of DateTimePicker or appearance. It will be impossible to change it in every control. I want my project to be flexible so I've got an idea..
I do separate custom controls for every type - string, numeric, date, byte.. and within I will put TextBox for example. And on every form I will put not TextBox, but MyTextBox. In fact, that MyTextBox will be just TextBox, but when I change something there, every control will be changed.
Is it good, popular pracitce in programming?
in the case of WPF this can be achieved quite easily using Styles and Templates.
in Winforms this is not possible, therefore I'd say your approach of deriving from the controls and using your own custom controls on the UI is a good practical approach which helps managing changes centrally.
If the controls were created manually in the programme, alternatively you could use a Factory clase(s) and get the Factories to create the controller object rather than just newing up.
But this might not be possible when the UI is created by dragging and dropping controls as the developer has no control over the creation of controls.
Which ever the approach you choose, the fundamental goal should be to centralize the creation logic of the controlls.
Yes, this is perfectly normal programming practice for GUI development, if the standard controls don't satisfy your requirements.
Most developers get 3rd party control suites for the extra flexibility. The benefits in buying far out weigh the benefits in building core controls yourself.
I've worked at a place that did companyTextBox, companyDatePicker and it worked ok. A couple of controls got revamped over .Net versions so these base classed controls required some surgery. Any depreciated controls were left as framework version dependent.
For special things, I do a lot of research into good custom controls on CodeProject, CodePlex, Code.Google.com,etc and implement them into the project I'm working on.
Otherwise use the stock standard controls or the suite of 3rd party controls the company I'm working for use.
My advice is to get a 3rd party suite of controls and make a ton of re-usable user controls based on the 3rd party ones. This way you can build most of the 200 forms by Drag and Dropping the user controls onto the forms. Make each User-Control Implement an Interface with Create,Retrieve,Update & Delete methods for the forms to generically work with your user controls.
I've done several WPF application(not using MVVM) in the past and I had always to implement my own system of navigation between view(instantiate the view once, and then load in a container component, with refreshing required components of my view).
It works, but:
It's always custom, so if a new developer comes he has to learn of it how it works
I'm pretty sure that It's not the most optimized(most of things haven't been done in background worker, ...)
It's a time loss
So I was wondering if there is an official way to handle this ? I don't exactly how, but I was thinking to a navigation component, which can act a little like a tab panel, or a little like the MVC framework in asp.net, we can call a specified controller for an action and some parameters.
Maybe deactiviting bindings when they aren't in the current view
You can use DataTemplates/Styles to customize content of your control ( not only apearance, but data, cause that what you're asking for I presume)
http://msdn.microsoft.com/en-us/library/ms742521.aspx
You can have one Host control and at runtime change its appearance based on events/ states.
Like an example can have a look here:
http://code.google.com/p/svnradar/ how this program manages a appearance of Group and Flat view of repository information.
Another example:
Podder of Josh Smith
http://joshsmithonwpf.wordpress.com/2008/03/05/podder-v2-has-been-released/
Hope this helps.
You may be interested by Lakana, a lightweight (but powerful) framework that can handle for you all the navigation concerns !
Riana
I am new to WPF. I have been reading a lot about WPF and dependency properties. My understanding of Dependency Properties is to bind properties to XAML (XAML being the target). I have envisioned a program in which a single configuration window would control all visual elements of the rest of the program (font, font size, colors, etc).
In my first attempt, I created a separate window that would contain all the different configuration options. This failed because I was unable to figure out how to use the dependency properties in separate XAML files.
Also, the dependency properties can only be registered in a class that implements directly or indirectly the DependecyObject class. How do I know which wpf objects implement it? It appears the window does not, but I could be wrong. My second attempt was this, to register the dependencies in the top window, so the whole visual tree would have access to it. I had exceptions being thrown and the only thing I could think of was that the window does not implement to DependencyObject. (I could be mistaken, and the visual tree thing is still sort of a mystery to me. I am learning though)
So now I'm at a loss. Is what I am attempting even possible? The whole purpose of this project was to help me learn WPF and now I'm wondering if I should lower my expectations of what I can accomplish with WPF.
Edit:
What kind of exception? What are you trying to do? Could you paste some code?
public partial class MainWindow : Window {
public Color BackColor {
get { return (Color)GetValue(BackColorProperty); }
set { SetValue(BackColorProperty, value); }
}
public static readonly DependencyProperty BackColorProperty =
DependencyProperty.Register("BackColor",typeof(Color),typeof(MainWindow),
new UIPropertyMetadata(0));
It appears that Color was causing the exception. I changed it to int and no exception was thrown. So are primitive types only able to be registered?
WPF is a framework to help you bulit really good looking apps (it includes also Printing etc.) What are you trying to do? Should it be a part of Visual Tree?
Again, this project was only meant to get me to learn WPF. My idea was to create a main UI with different pages. A configuration button would bring up a window with options to change font, fontsize, background color, etc. These changes would be applied in the main UI as the user made the changes. My issue has been how do I access those dependency properties outside of the configuration class where they were registered? How do I have one window that can have slider and combo boxes, and any other class can access those configuration settings?
Put simply, I would like that a single configuration (fonts and colors) be somehow inherited by all UIs. And that that configuration can be changed and seen by the user.
Also, the dependency properties can only be registered in a class that implements directly or indeirectly the DependecyObject class. How do I know which wpf objects implement it? It appears the window does not, but I could be wrong.
http://msdn.microsoft.com/en-us/library/system.windows.window.aspx
look at the Inheritance Hierarchy it does implement DependecyObject
My second attempt was this, to register the dependencies in the top window, so the whole visual tree would have access to it. I had exceptions being thrown and the only thing I could thing of was that the window does not implement to DependencyObject.
What kind of exception? What are you trying to do? Could you paste some code?
So now I'm at a loss. Is what I am attempting even possible? The whole purpose of this project was to help me learn wpf and now I'm wondering if I should lower my expectations of what I can accomplish with wpf.
WPF is a framework to help you bulit really good looking apps (it includes also Printing etc.) What are you trying to do? Should it be a part of Visual Tree?
We cannot tackle here the big task of learning a whole new framework and designing your whole program. That will take time. It can be daunting but stick with it.
As for your exception, the problem is that the mysterious:
UIPropertyMetadata(0)
is actually providing the default value for the dependency property and this value must match the type specified in the second argument to Register. Since 0 is an integer and your property is a Color the dependency property subsystem throws an exception. Instead you can use:
UIPropertyMetadata(new Color())
or any other color as the default.
Dependency properties are a newer design specifically created for WPF. One of the problems they solve is to create faster resolves of the property values because they don't use older, slower, techniques (Read up on why they were created).
They are hard at first, to understand, because it's not exactly clear why they are needed when there is support for the Interface named INotifyPropertyChanged. But one main reason (among others) is that if you implement a DependencyProperty correctly, you will be able to change the design time property values of that property in the property window! Now this is a very cool thing to do because you can very easily set all of your default properties that way.
Doing this for the sake of design time property editing allows you to learn a lot more about DPs and why they are used. In fact, some prefer them everywhere, as they just are not that hard to code up.
DPs are also used when creating custom controls using the "Generic" folder method. This is how Microsoft themselves create all their controls.
There are some caveats to be aware of when using them. You cannot see the design time properties of a DPs until that particular control is contained by something else. In other words a UserControl with DPs will not show those Dps in the UserControl design. They will; however, show up in the control that contains that user control.
DPs bring maximum control using Metadata, PropertyChanged callbacks, default values, and Cohersion and other techniques which give you 100% control of what they contain. The DP is the ultimate in property control.
Keep scouring the internet as there are tons of articles out there on the topic.
I'm looking at producing a few versions of my app with restricted functionality, and I'd like to leave out the code that is not necessary in simpler versions. Being a WinForms app, the UI will have to change for each version - not displaying the restricted controls.
I made an attempt to annotate parts of the auto generated controls & layout code with conditional compilation statements, but I discovered VS throws out all my code as soon as I touch anything via the WinForms designer.
I would like to be able to conditionally compile some event handlers & UI controls. I could write the conditional UI code outside the designer file, but then I wouldn't be able to use the VS designer to edit my app.. Are there any suggestions to remedying this situation - i.e. conditionally compile UI controls & still have them display in the designer?
Thanks!
Not knowing how your UI forms look like perhaps you can create a base form that all versions share in functionality. Then subclass that with forms for the specific functionality. This way you can conditionally compile the sub forms rather than trying to turn on/off controls within the one form. However the subforms will typically extend the form downwards so weaving controls throughout the form might not work in this case.
Also if you use a presentation pattern (if you are not doing so already) such as MVC or MVP you can minimize the logic you have in the forms and push that to presenter/controller or even business classes that you can configure based on the version you are compiling against. These classes can get injected (DI) into the application based on some configuration.
Another option is not to compile out the form controls but hide them based on the version you are running but have the business classes compiled. This way the important 'intellectual' code is not in the app and you're not fighting with the winform designer.