I am currently faced with a trivial task but I can't think of a solution.
In order to explain the theory of how it should work ...
There is a form of authentication. http://prntscr.com/pwat5
This form fits on TabControl -> TabItem and TabControl in turn is placed on the component Grid.
Actually, on that key input is an event by clicking authenticate and change the login form to another form.
Such forms of authentication, I need more, I went for it in the following way and laid the form data to a specific component, the structure looks like this:
Grid
ListBoxItem
MyAuthForm
... //Well, actually imposed on the rest of the crap form MyAuthForm
For an identical copy of my form MyAuthForm I clone the object, and to be more precise, I clone ListBoxItem together with all its contents to the new object and thus add it to the component Grid, that is, get a new cloned object.
Grid
ListBoxItem
MyAuthForm
... //Well, actually imposed on the rest of the crap form
ListBoxItemСlone
MyAuthFormСlone
... //And so on
But the problem is that my original object carries a variety of events but the cloned object can not deliver on certain events in the original.
How is it possible to solve this problem? To clone an object somehow could refer to the events of the original object?
In general, explained as best I could, I hope most accessible outlined what I want, thank you very much for any hints and ideas, the second day I suffer with this case and so far no ideas.
ps In the manual for each cloned object, I can not create events for such forms of authentication can be more than enough, everything has to be fast, so the only option is to somehow refer to already existing events, wpf allowed for that possibility?
Perhaps since you are working with WPF, if you bind the events to commands or any other mechanism then the cloned window, given the same datacontext would target the same methods and your problem would be solved.
I hope i understood correctly.
In the past i used Caliburn with WPF and there was something called ActionMessage there that might be of use to you.
It bubbles up through datacontexts until it finds a method with the specified name or else it throws an exception. Maybe you can use this, coupled with the fact that the 2 clones share the datacontext instance to enable you to make them all point to the same authentication method.
Hope i got it right.
Related
This question must have been solved multiple times by many people, however after several hours of research I still haven't found what I'm looking for.
What I have is a ExportSettings.settings file with a bunch of settings (bools, strings, ints, etc) and I want to create a View for them. In order to do it I've created a simple window in which I've placed standard buttons as OK, Cancel and Close and linked them to a KeyDown event to let the user accept/cancel using Enter/Escape.
I've created in XAML the needed Checkbox, TextBox, etc, for my settings. When the ExportSettingsView class starts, in its constructor I read my settings and assign the value for each control. In past I bound them directly but that unables the cancelation of changes, so I discarded it. When the user clicks OK button I assign, again, code-behind each value for each settings. If he clicks Cancel no assignment is done and the window just closes.
I would like something like EditableObject for my settings to avoid this ugly looking way of making my SettingsView.
Some of the things I'm looking for are:
Being able to put some comments in my settings would be nice (ToolTip)
Autogeneration of controls using reflection?
Avoid creating custom settings class (and the work of saving and reading everytime the application starts/shutsdown)
Break you problem up into parts to use MVVM, create your window and bind it to another class (ViewModel), this class will have properties on it that reflects the data in your settings file. this class also has to implement INotifyPropertyChanged. It can also implement EditableObject if you want, but frankly it isn't needed.
Hook you buttons up to Commands on your VeiwModel so that when the user hits save, it writes its properties to the settings file.
In this instance:
Window is your View
The new class is your ViewModel
Settings file is your Model
This will allow you to cancel changes, just dont write to your settings file when the user hits cancel.
The biggest point is that you DONT bind to your properties settings directly.
If you want auto generated fields for the view youll have to use a property grid, but with MVVM, your view is decoupled from you model so changing from things like textbox and such to a propertygrid would be easy.
When you do a search for MVVM, dont be fooled by people using a lot of terminology, MVVM is a very simple concept, it boils down to three classes, your View (xaml), View Model (what the view binds to) and Model (your data), THATS IT! good luck
I think you need something like this http://wpfdataform.codeplex.com/
And if you use ReSharper you can easily generate wrapper class for your settings
.NET already supports very nice tool for saving application and user variables. http://msdn.microsoft.com/en-us/library/aa730869(v=vs.80).aspx
It has to be saved explicitly so it might suit you very well. You can check what type the variable is and create a suitable control.
I use AvalonDock to have a vs-like docking style, and I use prism to inject views in my application.
Basically the user will have a panel on the side with one button per view loadable, and each time he presses one, I want to create a new tab on my AvalonDock's DocumentPane, and inject the right view in it.
Now I was under the impression that prism is good for this kind of scenario, but I can'f figure it out.
Also, I stumbled accross DocumentPane and DockablePane region adapters by Markus Raufer, have added it to my project and registered the mappings in the bootstrapper.
This allows me to compile the solution (so I'm guessing I'm getting close).
So far, I do this:
In my Shell I have a place with:
<avadock:DocumentPane avadock:ResizingPanel.ResizeWidth="500" Background="Transparent"
prism:RegionManager.RegionName="{x:Static inf:RegionNames.MainTabControlRegion}">
</avadock:DocumentPane>
In my code-behind, after Bootstrapping etc, I have a place that does:
m_RegionManager.Regions[RegionNames.MainTabControlRegion].Add(oneOfMyUserControls);
Executing this line doesn't show anything more to the user, but if i execute it twice, it will make an error saying a view is already registered (so it did add something!).
Furthermore, when i put a regular ContentControl, mark it with prism:RegionManager.RegionName="{x:Static inf:RegionNames.MainTabControlRegion} then add a UserControl in it the very same way I add it to AvalonDock's DocumentPane, it works. freaky
What am I doing wrong?
Thanks,
bab.
EDIT:
If define the MainTabControlRegion like this, the first view actually gets added, now id i add another one (different UserControl) it doesn't show it, but WPF Inspector says it's there.
From my point of view, it is indeed adding UserControls to a region, but it doesn't know how to create a new tab for each UserControl I add to the DocumentPane.
Since I'm not specifying anything about that, I'm probably missing a piece of code?
<avadock:DocumentPane avadock:ResizingPanel.ResizeWidth="500" Background="Transparent">
<avadock:DocumentContent Title="" prism:RegionManager.RegionName="{x:Static inf:RegionNames.MainTabControlRegion}">
</avadock:DocumentContent>
</avadock:DocumentPane>
I want it to create a new tab each time i add a usercontrol and insert it in there.
EDIT 2: Solution --> Here
This problem can be caused for many reasons.
Or the RegionAdapter is not well suited for the user controls you are trying to add, therefore I would recommend you to have a look at RegionAdapter implementation so you can have a good understanding of how it adapts your view in the region and customize it to fit your needs.
Or the user control you are adding has a particular behavior and is bugging the RegionAdapter when it tries to add your view to the DocumentPane items. Therefore you can customize the RegionAdapter or fix the user control behavior.
Or it is simply a data binding problem. The fact that nothing shows up on first execution is kind of strange. Try to inspect your DocumentPane property Binding with WPF Inspector. It saved my life more than once when dealing with custom RegionAdapters.
i originally had a main form with 2 panels, one had a graph in that i clicked on the other had the results displayed related to what you clicked.
All this code was dumped in the main form.
I tried to be a smart alec and use inheritance, so now i have a main form which has a graph objet and i have a superclass graph -> subclass specific graph heirarchy
however now when the graph is displayed in the main form, how do i get the data back to display in the other panel? The reason i ask this is now that the graph stuff is in its own heirarchy, it has no knowledge of the panel on the main form so i have no hwere to set the data when it is set
i hope someone can help
thanks
edit: i think i might just pass the control collection for the panel in to my graph class so i can add the relevant items in there
Depending on the relation between the two forms, you can use events to message data between them.
A click event handeled in the graph can raise an event with the data you need to display, which would end up on the owning form. Depending on the relationship, you either call a function on the 2nd form to display the data, or raise an event to which the 2nd form subscribed to send over the data.
[Edit]
I read Forms instead of Panels.
The main idea remains the same though. From your style of writing, it looks like you have an Objective C history. I know on the Mac, these things would be done in Interface Builder, setting bindings to make this stuff happen, but in the .NET Winforms you do these things in code (handeling events, calling methods, etc). If you like to stick more to the way it's done with Interface Builder, you might want to take a look at WPF applications; bindings work in a very similar way to how it's done on the Mac.
I would design this as an object that aggregates another object. Have a look at the way master-detail view works.
How is data binding in C# WinForms supposed to work when you have a Save button? I don't want the data updated until I press Save!
I have two forms (list and detail) backed by a BindingList<T> collection and my custom object from that collection, respectively. I can bind each form to the list or object appropriately. However, any changes made in the detail form are immediately reflected in the list form - I don't want to save the changes and update the details shown in the list until the Save button is pressed.
Is data binding designed to support this? Is there a common pattern for doing so?
Whichever way I look at it, binding doesn't seem to be able to support this scenario. I've considered the following:
Pass a clone of the object to the detail form, but then I have to reconcile the changes on Save - changes may have been made to the copy in the list in the meantime.
Implementing IEditableObject and calling EndEdit on save almost works as I can prevent the list being notified of the changes made until Save is pressed, but if something else causes a refresh the list is updated with the interim data.
I'm currently left with dispensing with data binding in my detail view, and doing it all manually. Which is rather annoying.
Data binding really wasn't designed for this kind of thing, unfortunately.
The best solution we've found here is to edit object clones, then reconcile the changes, as you mentioned. You may want to come up with a custom collection and/or object interface that helps you manage this type of thing.
Even if the cloning method is slightly more work up front, it's going to be wayyyy less complicated and frustrating than using IEditableObject trying to catch all the possible events that update the data. Not only that, it's a more straightforward approach, and you won't end up with spaghetti code.
If you are set on using a binding list, your best bet would be to implement IBindingList to create the functionality that you desire. It may also be possible to pull this off by simply inheriting from BindingList and overriding the appropriate methods to change the binding list's behavior.
http://msdn.microsoft.com/en-us/library/system.componentmodel.ibindinglist.aspx
If you are not set on using a binding list, it is probably best to do the data manipulations manually based off of the control's events.
Best of luck.
I am currently working on a program that uses a fairly complex structure of nested winform controls which changes dynamically as a user makes certain selections. To go into more detail about the specific layout of the controls would be to extensive for this question.
When ever a selection is made, a lot of updates are made to the underlying model which is controlled by the user controls. This then results in series of corresponding changes in the size/position/visibility of the displayed controls. All of these changes results in a painfully intense flickering of controls on the screen. I need to somehow fix this so that everytime the user makes a selection the screen is basically frozen until all of the control updates have completed.
I have attempted to use the Control.SuspendLayout/Control.ResumeLayout methods in many different places and ways and I can not eliminate the crazy flickering. I thought that suspending layout on the root control during the changes would fix the problem but it appears that this SuspendLayout doesn't help when child controls are changed.
Do I need to use some other approach rather than SuspendLayout? Is there a way I can debug SuspendLayout to see why it doesn't appear to be cascading to all of the child controls?
Suspend/ResumeLayout isn't your problem here. That only suspends automatic layout, the kind that is triggered by the Anchor and Dock properties. Double-buffering can't fix your problem either, that only suppresses flicker in each individual control. Your real problem is that you are updating too many controls at the same time, each will take its turn to paint itself and that takes time.
What you need is a different kind of double-buffering, compositing. Check out if the solution in this thread solves your problem.
In addition to #tommieb75's suggestion for double buffering, you can try and see if your root level controls have BeginUpdate/EndUpdate method pairs. These should help repress the repaints in between the calls.
If you are using WinForms 2+ then you can just set the 'Control.DoubleBuffer' property on the control to true (in the designer even).
With framework 2, setting DoubleBuffered sets the 3 flags : OptimizedDoubleBuffer, AllPaintingInWmPaint, and and another that I forgot, 'UserPaint' perhaps.
Also, do look at the BeginUpdate/EndUpdate as mentioned by #yetapb.
Use the SetControlStyles in the user Control, the flag is OptimizedDoubleBuffer which will prevent the flickering.