Best way to get parent Page control from Page inside Frame on desktop application built with WinRT/C++ UI.
Illustration:
MainPage
^^Frame
^^SecondPage
^^Frame
^^ThirdPage
^^Keep going
So, how to get MainPage control from SecondPage or even from ThirdPage onwards.
You can use the VisualTreeHelper to navigate the visual tree. The following implementation goes up the visual tree starting at a root element, and returns an element that matches the requested ancestor_type, or a null com_ptr if there isn't any that matches:
template <typename ancestor_type>
auto find_ancestor(::winrt::Windows::UI::Xaml::DependencyObject root) noexcept
{
auto ancestor { root.try_as<ancestor_type>() };
while (!ancestor && root)
{
root = ::winrt::Windows::UI::Xaml::Media::VisualTreeHelper::GetParent(root);
ancestor = root.try_as<ancestor_type>();
}
return ancestor;
}
You can use this to move from Page to Page, skipping over the intermediate Frame's until you are at the top of the tree.
Related
I'm working on a gatsby-react project that has multiple pages. On the header & footer there are links to other pages within my project. When I click on the link, the URL changes, the browser loads the new page and renders it normally.
The only problem is that the new page isn't loaded from the top. For example, if I'm currently viewing the bottom of the page and I click a link, then I expect to be taken to the top of the new page. What happens is I am taken to the new page, but I stay at the bottom. This image should explain what I mean.
I'm NOT using GatsbyLinks as they cause problems in the project, I use normal <a> tags for links instead.
Can I add anything to the <a> tag that can force going to the top of the page? If not then is there some other linking component I can use?
Thanks in advance!
The process of scroll restoration is handled automatically by Gatsby, however, using anchor links (<a>) for internal navigation (outside the scope of React) may lead to this kind of issue, since the data of the page it's cached but you are not using internal navigation to manage or restore it.
That said, I would suggest using the useScrollRestoration hook when needed:
import { useScrollRestoration } from "gatsby"
import countryList from "../utils/country-list"
export default function PageComponent() {
const ulScrollRestoration = useScrollRestoration(`page-component-ul-list`)
return (
<ul style={{ height: 200, overflow: `auto` }} {...ulScrollRestoration}>
{countryList.map(country => (
<li>{country}</li>
))}
</ul>
)
}
For a more global approach, you can also play with gatsby-browser.js APIs such as onRouteUpdate and shouldUpdateScroll, both triggered in each change of page (navigation):
exports.onRouteUpdate = () => {
if (typeof window !== `undefined`) { window.scrollTo(0, 0)}
}
exports.shouldUpdateScroll = args => {
return false;
};
By default, shouldUpdateScroll gets the last scrolled position, ideally, just changing and returning false it should work for your described scenario.
I wrote a class for my project like this using typescript and react.
class myImage extends Image {
oriHeight: number;
}
After I uploaded two images I have an array named 'results' which is full of objects with type myImage.
[myImage, myImage]
When I click it in browser, I could see the data of oriHeight of each element.
Then I try to use results.map() method to traverse all the elements in that array.
results.map((result: myImage) => {
console.log(result);
var tmp = result.oriHeight;
console.log(tmp);
})
However, the output of result is no longer an object but an img tag (because the type of Image is a HTMLElement) which makes the data of result unreadable. So the output of every tmp is undefined.
I am confused about that. Why the myImage object will become an img tag when I want to traverse it? I hope someone could help me with that. Really appreciate it.
I bet your data is actually fine. When you console log an html element, the chrome console displays it as an html tag instead of the javascript object.
Update: It's generally a bad practice to add your own properties to DOM elements because they're harder to debug and you risk them being overwritten by future browser properties. Instead, you could create a javascript object that contains both the image and your custom property. Here's an example interface definition:
interface MyImage {
imageEl: HTMLImageElement;
oriHeight: number;
}
I am using the library dragula for doing some drag & drop stuff.
Dragula internally uses cloneNode(true) to create a copy of the dragged element that will be appended to the body to show the preview image while dragging.
Unfortunately, if dragging a polymer element, the bound data get's not cloned. By consequence the contents of the dragged element (e.g. <div>[[someString]]</div>) are empty.
Is there a solution for this?
I actually do not need the data to be bound for my element, it is just a "read-only" element that displays some data that does not change after being initialized. Is there maybe a way to somehow "resolve" the strings to the html without being bound anymore?
Thank you already!
Found a solution myself. You have to override the cloneNode method inside the polymer class:
cloneNode(deep) {
let cloned = super.cloneNode(deep);
for (let prop in MyClass.properties) {
cloned[prop] = this[prop];
}
return cloned;
}
In codedUI I am unable to traverse by GetChildren() method in an html page with HTML5 tags.
My Html structure is like this.
HTML
|-BODY
|-DIV id="pagetop"
|- HEADER class="headerclass"
|- NAV class="navclass"
|- SECTION class="sectionclass"
|- FOOTER class="footerclass"
|- DIV id="lastdiv"
Issue: On doing GetChildren() on "pagetop" div control, only 1 result is returned having "lastdiv" div control in it.
It should return 5 controls instead.
I am able to capture the UIMap for SECTION(or other HTML5 tags) and able to traverse backward by GetParent() method, but the other way is not working.
SECTION.GetParent() = DIV id="pagetop" [Works as expected]
SECTION.GetParent().GetChildren() = Only 1 result [This is wrong, should be 5]
Is there an issue with traversing HTML5 tags in codedui?
Try looking at the child controls of the one control that is found. I am not aware of anything that says the HTML structure you show MUST be represented with exactly the same number of levels. Phrasing that differently, the UI Controls might have extra levels than the minimum that appear to be necessary for the HTML structure.
To understand how the HTML is represented you could use the Coded UI cross-hairs tool. Start with one of the five sections (or a child of theirs) and then use the four navigation arrows to move up through the hierarchy to see what items Coded UI can see at each level.
Another approach might be to use recursive code that calls GetChildren() to descend the hierarchy and show exactly what is present at each level. You might use code based on the recursive routine in my answer to this question Recursively locating a UIElement with InnerText in C# but using a small maxDepth and adding some Console.Writeline() or other print statements to display the controls found.
I have filed one bug in VS2013 feedback forum for this issue.
It can be tracked here: https://connect.microsoft.com/VisualStudio/feedback/details/898599/
Based on suggestions from AdrianHHH, I am currently doing this to get all the children of a control. This returns all controls including HTML5 controls as HtmlCustom.
private List<UITestControl> GetAllChildren(UITestControl uiTestControl)
{
var child = new HtmlControl(uiTestControl);
child.SearchProperties.Add("InnerText", "", PropertyExpressionOperator.Contains);
var items = child.FindMatchingControls().ToList();
var trueChildren = items.Where(i => i.GetParent().Equals(uiTestControl)).ToList();
return trueChildren;
}
I want to make some extensions to CodeMirror. The addWidget method seems like a promising starting point. The documentation states
addWidget(pos, node, scrollIntoView) Puts node, which should be an
absolutely positioned DOM node, into the editor, positioned right
below the given {line, ch} position. When scrollIntoView is true, the
editor will ensure that the entire node is visible (if possible). To
remove the widget again, simply use DOM methods (move it somewhere
else, or call removeChild on its parent).
I don't really understand what that means or what I would use it for. I cannot find a usage of it in the CodeMirror codebase nor anywhere else in google.
You need to pass an html node and a position and a Boolean value
// create a node
var htmlNode =document.createElement("h1");
var text = document.createTextNode("Text or whatever");
htmlNode.appendChild(text)
// call this after you initialized the editor.
// the position must be like this {ch: YourCharecterNumber, line: YourLineNumber}
editor.addWidget({ch:30 , line: 1},htmlNode, true)