I have a UserControl that has visual states in it. When the control constructs, I want to move to one of the states which is the "initial" one (not Default - there are modifications).
public MyUserControl()
{
this.InitializeComponent();
Loaded += MyUserControl_Loaded;
VisualStateManager.GoToState(this, "HideImageState", false);
}
However, when the control loads up, there's an obvious transition happening (the one that HideImageState represents).
Why is that if I am passing in useTransitions?
Since you aren't providing any more information, there are few things to work through "generally" that might help. Again, I am shooting from the hip with common problems...
The first is that your storyboard is inaccurate. If you created your transitions in Blend, then this is not likely. But if you coded them by hand, then the targets may not be what you expect.
The animations could also be occurring but being occluded by other elements in the UI. This can sometimes occur when you are resizing an object inside a container that cannot stretch.
Finally, and most importantly, if your visual state transitions are in a user control that is wrapped in a Viewbox then your view states are ignored for some reason.
There are other possible reasons for you to get the result you are seeing. However, with so little information given, I can't keep on guessing. I would assume one of the above three reasons.
Best of luck!
Related
I am reusing the same code for clearing the screen many times in my program, and I thought about turning it into a class, but I still don't get how classes work and how to properly make one.
My code to clear buttons and other controls is as follows:
List<RichTextBox> _richTextBoxes = this.Controls.OfType<RichTextBox>().ToList();
List<Button> _buttons = this.Controls.OfType<Button>().ToList();
List<Label> _labels = this.Controls.OfType<Label>().ToList();
List<TextBox> _textBoxes = this.Controls.OfType<TextBox>().ToList();
foreach (var rich in _richTextBoxes)
{
this.Controls.Remove(rich);
}
foreach (var button in _buttons)
{
this.Controls.Remove(button);
}
foreach (var label in _labels)
{
this.Controls.Remove(label);
}
foreach (var textBox in _textBoxes)
{
this.Controls.Remove(textBox);
}
As others already mentioned, it's a rare practice to remove/create all controls of a container (Form, Panel, etc) at runtime, and a possible waste of PC resources.
Of course you can use:
Form.Controls.Clear();
Or
Panel.Controls.Clear();
But, what's wrong with placing all your controls in a Panel, for example, and simply hiding said panel? seen you get the same result in a more efficient way
If you opt for this, it's as simple as this line:
Panel.Visible = false; // or true
Hiding 100s or 1000s of controls is inefficient and wasteful
Contrary to the other answer's idea that
Panel.Visible;
...is somehow more efficient, it is not. Hiding a control does not release any resources the control might have requested the obvious being a window handle. Handles, fonts etc are all part of the GDI pool, a rather limited resource. Depending on what version of Windows you are running you might be limited to anything between 256 and 16,384 GDI handles per process.
So think before hiding 100s of controls. Much better to just destroy the unwanted and create the ones you need.
Back to the question
I am reusing the same code for clearing the screen many times in my program
The bigger question is why you want to do that?
Though a legitimate programming scenario, given that "but I still don't get how classes work" , it is unlikely you are at the dynamic-UI-apps stage based on say dynamic selection of a database table.
Consider creating multiple forms via the Designer and don't modify them at runtime. That's alot easier if dynamic UIs isn't really a requirement.
An easier way to change things at runtime
Otherwise if you are super keen to continue with changing things at runtime, consider placing all the controls in a child Panel belonging to the form.
Then you can just call Clear():
myPanel.Controls.Clear(); // Job done
I'm creating an OverflowPanel derived from the WPF Panel class. The intent is that it will fill with items in a single direction, and when there are too many items to display, excess items will be removed and replaced with another control to hold the overflow. Think of a website's breadcrumbs, or the address bar in Windows File Explorer. This is a .Net Core 3/C# 8 project.
I have a partially working solution: I've inherited from Panel and overridden MeasureOverride() and ArrangeOverride() to get the behavior I want. My problem now is getting a button or some other control to display in place of the items being removed.
My initial, naive approach was to just create a Button in code and try to Measure/Arrange it.
public class OverflowPanel : Panel
{
// First by itself, but I did also try to host this in a new UIElementCollection
private readonly Button _overflowButton = new Button();
public override Size MeasureOverride(Size availableSize)
{
...
_overflowButton.Measure(availableSize);
// Do stuff with _overflowButton.DerivedSize.
...
}
// Also attempted to draw int in ArrangeOverride()
}
This did give me non-zero result for the measurement. (I put some dummy content in the button.) My algorithm gives me space on the screen where the button should go, however, nothing gets rendered there.
I also confirmed that there wasn't simply a button being drawn with no visual style, by inspecting the Live Visual Tree in Visual Studio.
I tried to make a UIElementCollection and add the button to that to see if it would add it to the visual tree, but this also did not work.
Most Google/StackOverflow results I've seen suggest something along the lines of this.Children.Add(_overflowButton), but this does not work when hosted inside an ItemsControl, as it takes over managing the collection of objects and throws an exception if you attempt to mess with it.
After digging around in the code for Panel and UIElementCollection, I noticed that Panel lets you override
UIElementCollection CreateUIElementCollection(FrameworkElement logicalParent)
to use a derived implementation of UIElemenetCollection. I created a PinningUIElementCollection to trick WPF into rendering the extra element. It stores extra items and then slips them in whenever the iterator is accessed. It also does index mangling to access both the extra collection of items and the automatically generated one.
This actually worked. My button is now displayed (albeit without the correct styling, but that's a separate issue.)
However my issue with this approach is that it seems like a lot of work. It also seems error prone: I could easily miss when it tries to use a numerical index and forget to mangle it, causing unpredictable results.
Is there a simpler/more straightforward way, in my derived Panel implementation, to display an extra button or some other arbitrary control with only a few less hoops?
I believe the proper term is recursively. I have a Windows Form, and inside that I have a Tab Control, and inside the Tab Control are four Tabs, and inside each tab are multiple controls - Buttons, text boxes, etc. I want to change the cursor of every button to a type hand.
Below is where I have gotten so far with this inquiry:
foreach (Control c in tabControl1.Controls)
{
// The only controls that will be found here are the tabs themselves. So, now I must run a *foreach* loop through every tab found, and look if buttons are present.
}
The commented area explains my issue to some extent. I have found an example of a recurisively finding a control on a form but I am not sure why I would need to pass the contro's name as an argument as I am trying to find Every control of type button.
Here is the code that I found online:
http://www.dreamincode.net/code/snippet1663.htm
Thank you once again. I love hearing from all of you as it's an excellent learning experience for me.
Thank you very much for your time.
private void FindAll(Control myControl)
{
if (myControl is Button)
doStuff();
foreach (Control myChild in myControl.Controls)
FindAll(myChild);
}
I believe this will work. When you call it the first time, you'd pass in the form. The form isn't a button, but it will have children. Each child it has will be passed into FindAll(). If that control is a button, it will call doStuff() (you can set the cursor in there). Likewise if that control has any children, they'll be passed in.
You are correct, the term is recurisve (generally speaking, any function or sub that calls itself). So, in this example FindAll() will call FindAll() in a certain case.
Also, this is just sample code; you may want to check for null references depending on the nature of your application.
EDIT: Just as an FYI if you aren't familiar with recursion, it's pretty easy to get the dreaded StackOverflow exception. When you end up in a never-ending loop of calling yourself, you'll run out of stackspace and see the StackOverflow exception. Hence, the name www.StackOverflow.com
In this case, we don't have to worry because .NET prevents us from adding controls that create a circular reference. For example - this code will fail:
GroupBox g1 = new GroupBox();
GroupBox g2 = new GroupBox();
GroupBox g3 = new GroupBox();
g1.Controls.Add(g2);
g2.Controls.Add(g3);
g3.Controls.Add(g1);
I don't know if any of this makes sense, but hopefully it helps. Recursion is generally considered one of the 'harder' concepts to grasp for a lot of people. Then again, I'm not very good at explaining things.
You are correct that the correct term is recursion. In the link you have posted, it is indeed recursive because the function calls itself, which is a property common of recursive functions.
The function needs to take a Control instance because the function is trying to solve the problem "For a given control (which is the Control container that is passed in), find all controls inside." Notice how this method doesn't care about what 'level' the control is at, it can solve it regardless.
You are correct that if you ran the code in your example, it would not work. It would only pick up controls one level inside of the 'parent' control. This is why the function needs to call itself.
With the function calling itself, you get the following:
Call function with the outermost control.
Do I have any children?
If so, call the same function again for each child (which will again ask "Do I have any children?" on the child).
By calling the function inside the function, you will hit all levels.
WARNING: Just as a note of caution, recursion used carelessly can lead to problems. If you apply this on something that has 1000 'levels', your algorithm will take forever and possibly crash as you will run out of memory to handle it, since it is digging deeper and deeper (a stack overflow!). Separately, I suspect there is a better way to do what you are doing such that you don't need to use recursion, although it will work.
Hope this helps!
In a program I have written users can add controls to the form and move them around and set some properties in a pseudo design mode. I want to be able to lock all these controls into one location when they press a button to switch to "data mode". How can I do this? I wanted to do be able to loop through all the controls and use the Lock Property but I noticed it didn't show up in intellisense.
Thanks!
The Locked property is not a real property -- it is one which is added in by the Windows Forms designer (like the Generate Member and Modifiers "properties"). You would therefore need to simulate it yourself, either at the form level or (if required) at the control level (say with a dictionary of which controls are locked), and manually check it in the code you've written for moving controls around.
I am assuming by "pseudo-design mode" you do mean that your application is in a run-time state, and the end-user is experiencing a "virtual design mode" : please correct me if I am wrong.
But, I am assuming you are referring to the design-time 'Locked property of controls, and that you wish to "emulate" this at run-time ... correct ?
I'm also assuming you are attaching mouse up/down/move handlers to the controls you do allow to move around, probably by looping through all, or a subset of, the controls on the form (or a collection you are maintaining of controls allowed to be moved).
If my assumptions are correct, I would go for removing the event handlers that enable moving when you need to disable control movement, then restoring those event handlers when you need to allow controls to be moved again.
One main reason being that it is, imho, "best practice" to control event-handling rigorously (leaving event handlers "in-place" can interfere with object disposal ... although that may, in no way, apply to your scenario here).
One more idea : you have an "invisible" Panel docked 'fill to the Form : on this panel are all controls that can be moved : this may allow you to more easily "narrow your focus" on which controls you "spend" this extra code on. The drawbacks in using this approach are usually :
if you use hostingForm.ActiveControl to determine which control got the mousedown (and, thus, can then be moved) : you'll find some controls, like labels, and pictureboxes, do not become the activecontrol of the form when clicked, but most do.
you have a "z-order" thing to think about since a control not in your panel encapsulating the controls you wish to allow to move sent behind the pseudo-transparent panel will be hidden.
For these reasons, imho, I think disabling and re-enabling event handler attachments is best, most simple, and since it can be done when the controls are "down-cast" to their control "identity" :
private void enableControlsMove()
{
foreach (Control theControl in panel1.Controls)
{
Console.WriteLine(theControl.Name);
theControl.MouseDown += new MouseEventHandler(theControl_MouseDown);
theControl.MouseUp += new MouseEventHandler(theControl_MouseUp);
theControl.MouseMove += new MouseEventHandler(theControl_MouseMove);
}
}
private void disableControlsMove()
{
foreach (Control theControl in panel1.Controls)
{
Console.WriteLine(theControl.Name);
theControl.MouseDown -= theControl_MouseDown;
theControl.MouseUp -= theControl_MouseUp;
theControl.MouseMove -= theControl_MouseMove;
}
}
I use it this way.
best, Bill
Locking controls prevents them from
being dragged to a new size or
location on the design surface.
However, you can still change the size
or location of controls by means of
the Properties window or in code.
MSDN
I guess it's a visible-to-designer-only property. I think you'd have to implement your own freeze mechanism - a little flag to toggle between Design and Use modes.
Update: It seems that custom designer classes can add properties to controls based on whether they are in Design Mode or not.
More details available here if you intend to take the VS architectural hammer path. In any case, worth 10 mins of reading time.
Custom Design-time Control Features in Visual Studio .NET - Dino Esposito
I have subclassed a Treeview and on instantiation it loads a new ImageList (and the associated Images).
Whenever I switch to the designer view, it's also trying to run this code, however the images aren't in the designer's path, so it crashes. I ended up putting in a hack to see if the current directory is "Visual Studio", then do nothing... but that's so ugly.
I find this happening for other things. If a control is trying to use objects during load/initalization that are only available while the program is running, then the Design View cannot bring up the control.
But is there a way to get around this?
I guess what I'm hoping for is having a try/catch for the Designer (only) with the ability to ignore a few errors I know will be happening (like FileNotFoundException, etc.).
Thanks
Everything that inherits from System.Windows.Forms.Control has a DesignMode property that returns a boolean indicating if you are in design mode or not. You could use this to determine when to/when not to load external resources.
Usually it is better to move the loading of these resources to an override of OnLoad as they are rarely required directly at construction. This fixes the issue you are seeing and means that only trees which get displayed at least once will perform these additional resource loading steps.
Otherwise, you can just exclude these steps during design time by checking the DesignMode property and acting accordingly.
This is a fine pattern to use if you're making a control library with a sample of images when shown in the designer or hook ins to other designer features but as a pattern for development I'm not sure it's very effective.
I would suggest shifting your "business logic" (in this case your loading of certain images into a treeview) outside of the bounds of your treeview control. In your case I would place the logic within the Load event of the form that the control is inside:
public void Load(object sender, EventArgs e)
{
string path = "c:\somePath\toAwesome\Images";
myFunkyTreeView.AddImages(path);
}
For larger apps I personally think you want to shift the logic even out of the forms themselves, but this is debatable measure as it requires additional plumbing as a trade-off for the flexibility this provides.
Thanks for pointing me in the right directioon guys.
I had tried registering to the OnLoad event, but that event is triggered when the Design View comes up, so that didn't quite work for me (am I doing something wrong?).
Anyway, I looked a bit more into the DesignMode property. It can only work for Controls, and sometimes your object may not even be a control.
So here's the answer I prefer:
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) {
// design-time stuff
} else {
// run-time stuff
}
Found it here.