I know we can use
VisualStateManager.GoToState(this,"SomeState1",true);
to enter into SomeState1 , but now how to go back to the base state, like no state, the state where the control was loaded in.
VisualStateManager.GoToState(this,"base",true);
// OR
VisualStateManager.GoToState(this,"",true);
// OR
VisualStateManager.GoToState(this,null,true);
The problem is if there is no such way to go back to the initial or base state then I will have to always create a first state and in the contructor goto the first state in the start of control.
I didnt find any documentation, so I am trying all combinations but didnt find any working one..
Normal != Base.
Base is just the control's initial state before any visual state is applied (i.e. before the VSM is active).
If you read this article on the Expression blog there is a good description which I have lifted here:
... when you author your own templated
control or UserControl, you should
define a ‘default’ state in each state
group. Have the control go to those
‘default’ states when it initializes,
and do so with transitions suppressed
so that it happens without delay. Once
it’s on the state graph, the control
is ready for state transitions to
occur so now you can implement the
event-handlers that trigger the
transitions within the state graph.
From a brief look at the VSM source code, it appears there is no way to get out of the VSM and back to your original Base state... so yes, you do need a "Normal" state. :(
I also find this a bit annoying that the VSM state cannot be removed easily, although the above solution does makes sense. Maybe they will fix this in the future.
To do this, you have to first define your "base" state.
The deal is, if you define a visual state that doesn't contain a storyboard, then this state will effectively be equal to the "base" state - the one that the control was loaded in.
<VisualStateGroup x:Name="TheGroup">
<VisualState x:Name="SomeState1">
<Storyboard>
...
</Storyboard>
</VisualState>
<VisualState x:Name="BaseState" /> <!-- Note: the VisualState tag is empty -->
</VisualStateGroup>
Then switch to that state:
VisualStateManager.GoToState( this, "BaseState", true );
The default controls define a "Normal" visual state in the CommonStates group, which is reverted to on mouseout etc. I think you'll need to follow the same pattern for what I assume is a custom control?
Related
ngOnChanges is deprecated in favour of ngAfterChanges, but the former was given a list of properties that changed. The latter gets nothing. How do I know what changed so I can only perform expensive actions if a particular #Input changed?
Calculating the list of changes was actually expensive itself. So it was dropped instead I would suggest having a setter mark if something has changed for just the expensive inputs.
We've started using VirtualTreeView v5.5.3 with Delphi7 since 1 year and love it!
We would like to use the full potential of the component, but there is only a little information about the BeginSynch method in the help file.
When should BeginSynch + EndSynch be used compared to BeginUpdate + EndUpdate?
Which one should be nested into the other?
What methods can be used in which case? (Sort, ScrollIntoView, MoveTo, NodeHeight, isVisible[], ... ) to group manipulations before painting to speed up the app?
To my understanding they have different, almost opposite purposes, and for your use case you would need BeginUpdate.
BeginUpdate is typically called when you want to do a lot of updates, and you don't want redrawing etc to happen during that process. Many controls, including TListBox and TDBGrid, have this possibility to speed up bulk updates.
BeginSynch is related to events, especially the OnChange event. The VirtualTreeView can fire the OnChange event with some delay when you set the ChangeDelay property to a value higher than 0.
This also means that you may miss some events. If you make two changes in rapid succession, you may only get one event, or you may get the event later than desired.
BeginSynch will start a synchronous mode that fires the OnChange event immediately after (in sync with) the change being made, overriding the ChangeDelay property. Starting this sync mode is easier than saving the value of the ChangeDelay property and restoring it afterwards.
So in a way, you could say that BeginUpdate and BeginSync are almost opposites of each other, in terms of speed, but really it's just about what your usecase is. For your case ("grouping manipulations") you would definitely use BeginUpdate.
The documentation on BeginSynch could be a bit more clear in this regard. It refers to BeginUpdate because it's a similar kind of mechanism (entering some kind of update mode, with a correlating EndSomething method), while actually it should refer to ChangeDelay which it is functionally related to. It's also interesting that the 'Send feedback' link at the bottom of the documentation is not actually a link...
I have a huge VCL Forms application in delphi and there is an option to display or hide a certain control (MyControl) on each form. Right now the traditional option is enabled, so MyControl should be hidden at runtime.
In Delphi Designer both Controls are visible. Every form is derived from a MyForm-class and in its OnCreate-Procedure the Visible-property of a MyControl (if available) is set to false (according to the traditional option enabled). This does work (as I can see with breaking points and watching expressions). For almost all forms this results in the MyControl not showing.
However for one certain form at some point the MyControl-component itself or any other part of the program sets the MyControls' visibility to true again. How do I find out where this happens?
I am using Delphi 10.1.
my approach:
I've tried to watch the visible-property through the watching-expressions-window using several breaking points. But of course the watching-expression is not available anywhere in the Code (myControl.Visible will only work if the breakingpoint is somewhere myControl is defined). I set a breaking-point anywhere I could evalute myControl.Visible but the magic seems to happen somewhere in between.
So my question: is there some kind of a global variable name, so that I can evalute and watch the visible-property wherever the debugger pauses the program?
a different approach:
I set a data- and an address-breakingpoint but they never fire. Only when I close the program they pause the program a few times.
As advised in the comments, if this is your code you can modify the property to use a Setter and then set a breakpoint on the setter. However if this is not your code and it simply exposes the variable (field) then changing the code to include a setter can be anywhere from triovial to impossible depending on what else needs to be recompiled when you make the change.
If this is your own custom component then you can redeclare an inherited property to use a setter.
If this is not your own custom component - you could make it a custom component and simply change the setter for the property.
You can set a memory breakpoint to alert you to when a memory location changes but your success with this may vary.
I encourage you to experiment with the conditions you can put on breakpoints, get the debugger to work for you.
I've been tasked with supporting an application that is written in Delphi, which is occasionally crashing with the error message "Control '' has no parent window".
My question is not to understand WHY the error is happening, but to understand why the control has no name assigned.
Is the seeming lack of a name for the control a function of the way the control was coded (i.e., controls can have names but they are optional), or is this because the name of the control is inherited from the (non-existent) parent?
My question is not to understand WHY the error is happening, but to understand why the control has no name assigned.
Controls that are created at runtime, as opposed to design time, need not have names. So, this control has no name because the programmer created it without naming it, or it is a control created internally by another control, without being named.
It is perfectly normal for controls not to be named. It is perfectly reasonable for complex applications never to refer to control names.
There are multiple reasons, including but not necessarily limited to:
1) It wasn't given a name in the code.
2) It doesn't inherit a name for whatever function called it
I have a utility routine that I call when validating user input in a dialog fails. It sets focus to the offending control, beeps and displays an appropriate message to the user. This works well as long as the offending control is not hidden. Now I have to adapt this to a situation where the relevant controls are children of some kind of collapsible group boxes (possibly even nested), and I have to make sure that the "ancestor" boxes are expanded before calling SetFocus.
Now I have a few possibilities:
Build knowledge about the collapsible component into the error reporting routine. I'd like to avoid that as the routine should rather stay generic.
Pass an callback that can be called prior to (or instead of) SetFocus. This is error prone because one has to remember to pass the callback at all the relevant places.
My favourite solution would probably be an event (or overrideable method) (probably in TWinControl) that tells a container control "please make sure you and you child controls are visible" but I don't know of such a thing.
Any ideas how I can handle this situation?
Define an interface with a method called something like: EnsureVisible.
Implement it for all your components (you may need to derive your own versions of some of these components). This allows different controls to have quite different behaviour.
When a control needs to make sure it is visible it walks its parents and calls EnsureVisible if the interface is implemented.
If you don't like interfaces then do it with a custom Windows message, but you get the basic idea.
In my opinion the best solution would be a separate routine that builds knowledge about all container controls, allowing the dialog validation routine to stay generic and at the same time being focused enough to be easily tested and maintained. Something along the lines of:
procedure ForceControlVisible(C: TControl);
begin
// Recursive code
if Assigned(C.Parent) then ForceControlVisible(C.Parent);
// Code specific to each container control class
if C is TTabSheet then
begin
// Code that makes sure "C" is the active page in the PageControl
// goes here. We already know the PageControl itself is visible because
// of the recursive call.
end
else if C is TYourCollapsibleBox then
begin
// Code that handles your specific collapsible boxes goes here
end
end;
OOP-style methods that rely on virtual methods or implementing interfaces would be way more elegant, but require access to the source code of all the controls you want to use: even if you do have access to all required sources, it's preferable not to introduce any changes because it makes upgrading those controls difficult (you'd have to re-introduce your changes after getting the new files from the supplier).
Each component knows its Parent. You can walk up the list to make each parent visible.