How to anchor a WPF Popup to a Control? - c#

I have decided to use templated PopUps to display validation errors for my controls, rather than ToolTips (seem to offer greater flexibility in terms of styling). I am looking for a clean way to ensure that the PopUps are anchored to the control they are referring to so when the window is moved they are moved with them...
One thought i had was to traverse the visual tree and manually set all PopUps IsOpen property to false...this seems like a bit of a "hack". It is less than ideal as it will presumably flicker among other things...Having said this a lot of the solutions i have seen so far on stackoverflow also seem to have their pitfalls. Ideas?

// Reference to the PlacementTarget.
DependencyObject myPopupPlacementTarget;
// Reference to the popup.
Popup myPopup;
Window w = Window.GetWindow(myPopupPlacementTarget);
if (null != w)
{
w.LocationChanged += delegate(object sender, EventArgs args)
{
var offset = myPopup.HorizontalOffset;
myPopup.HorizontalOffset = offset + 1;
myPopup.HorizontalOffset = offset;
};
}
From this link

Related

WinForms : Dynamically add / remove AnchorStyles to / of control

I am currently working on a Editor, which lets the user design his own WinForm overlay, at least to a certain point.
Therefore I want the user to decide, which AnchorStyles the current selected Control should have. I would like it to be handled by checkboxes. Here's how I had it in mind:
As you can see, the user has currently selected a dynamically added Panel, called Grid. Handled by the CheckBoxes to the right, he should now be able to set the selected Controls AnchorStyles.
Here's my problem: I can't seem to find a usable solution, to dynamically add a specific AnchorStyle to the already existing ones, or the opposite, remove the AnchorStyle, but keep the other ones as they are.
I was trying to get it to work with...
SelectedControl.Anchor += AnchorStyles.Top;
which doesen't work at all. So i thought of this...
SelectedControl.Anchor = SelectedControl.Anchor | AnchorStyles.Top
which I imagine could work, but I haven't even tested it, since I wouldn't know how to remove ones unchecked AnchorStyle.
Building a gigantic if(){} else if(){}... doesen't seem to be a good Idea :)
I'm open for any ideas / solutions.
Thanks in advance!
Assuming you have four check box controls named top, bottom, left and right, you can handle CheckedChange event of them using a single method and set the anchor of the desired control based on the checked value of the controls. For example:
private void checkBox_CheckedChanged(object sender, EventArgs e)
{
var values = new[] { top.Checked, bottom.Checked, left.Checked, right.Checked };
byte[] data = new byte[1];
new BitArray(values).CopyTo(data, 0);
selectedControl.Anchor = (AnchorStyles)data[0];
}
Note: AnchorStyles is a flag enum having top=1, bottom=2, left=4 and right=8. Using above code I've mixed those flags to create the AnchorStyles and have assigned to the Anchor property of control.

Close HamburgerMenu with slide gesture

I'm trying to implement a slide gesture to open/close the hamburguer menu control, but I'm having trouble closing the menu with version 1.5.1 of the control. With version 1.4.1 I close the menu this way:
var paneGrid = HamburgerMenu.FindDescendantByName("PaneGrid") as Grid;
paneGrid.ManipulationMode = ManipulationModes.TranslateX;
paneGrid.ManipulationCompleted += OnPaneGridManipulationCompleted;
private void OnPaneGridManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) {
if (e.Cumulative.Translation.X < -50) {
HamburgerMenu.IsPaneOpen = false;
}
}
But with version 1.5.1 the listviews take all space in the control and "OnPaneGridManipulationCompleted" does not get fired... any ideas please?
You can try setting both HorizontalScrollMode and VerticalScrollMode to Disabled on the ListView's inner ScrollViewer to let touch input bypass it.
Since the default value of HorizontalScrollMode is already Disabled. You just need to manually set the VerticalScrollMode as below
if (HamburgerMenuControl.FindDescendantByName("ButtonsListView") is ListView listView)
{
ScrollViewer.SetVerticalScrollMode(listView, ScrollMode.Disabled);
}
The side effect is that you can no longer scroll the ListView vertically. But generally you wouldn't want that(bad design) anyway.
You might also be interested in this answer of mine. :)

UWP CustomRenderer for Checkbox: Pointer over Checkbox changes style?

I'm working with Xamarin.Forms and I made a CustomRenderer for Checkbox in UWP. When I set all the Checkboxes of my items in the ListView to true by clicking the button "Alle", the Checkboxes are displayed correctly with the check inside the box:
However, if I hover my mouse over the Checkboxes, they immediately change their appearence (the check disappears but it's still selected). In the following screenshot, I moved my cursor over the 3rd - 7th Checkboxes:
This is my overridden OnElementChanged method in the CustomRenderer:
protected override void OnElementChanged(ElementChangedEventArgs<EvaCheckbox> e)
{
base.OnElementChanged(e);
var model = e.NewElement;
if (model == null)
{
return;
}
nativeCheckbox = new CheckBox();
CheckboxPropertyChanged(model, null);
model.PropertyChanged += OnElementPropertyChanged;
nativeCheckbox.Checked += (object sender, Windows.UI.Xaml.RoutedEventArgs eargs) =>
{
model.IsChecked = (bool)nativeCheckbox.IsChecked;
};
nativeCheckbox.Unchecked += (object sender, Windows.UI.Xaml.RoutedEventArgs eargs) =>
{
model.IsChecked = (bool)nativeCheckbox.IsChecked;
};
SetNativeControl(nativeCheckbox);
}
I tried to override the PointerEntered event of nativeCheckbox. It works, for example if I set the model.IsChecked to true on this event, it will be set to true:
nativeCheckbox.PointerEntered += (s, args) =>
{
model.IsChecked = true;
};
But I don't know how to (if even at this place) prevent the checkbox from changing it's appearance when moving the cursor above the Checkbox. Just leaving the triggered event with empty code like this won't change anything about the described behaviour:
nativeCheckbox.PointerEntered += (s, args) => { };
How can I prevent the Checkbox from changing it's appearance when I move my cursor over it?
Update:
I've created a sample project for this issue. You can find the repository here: https://github.com/Zure1/CustomCheckbox
It has the exact same described behavior. In the following screenshot I pressed the button "All" on the bottom of the screen and then the checkboxes look like correct with a check inside of them:
After moving the mouse cursor over the bottom 3 checkboxes, their change their appearance:
Information: I'm debugging on my desktop (Windows 10). I don't know if this issue exists on WinPhone. Just in case you're wondering why my checkboxes are red: My system color in Windows is red.
This is a tricky one as I have been struggling with this issue for a while, I'll try my best to answer this.
TL;DR: It's caused by ViewCell.
The issue comes down to Xamarin Forms ListView and ViewCell.
I haven't been able to track down the cause yet for many months and the way I get around this issue is by refreshing the ListView every time a change happens forcing a redraw of the entire ListView which can really impact performance.
My educated guess on what the cause could be is the rendering code for the ViewCell is missing something.
As for your particular issue, I have created a CheckBoxCell which you can use to display a list of checkboxes with a title. I forked your project and made the changes.
This will display something similar to what you are trying to achieve and doesn't have rendering issues so will be a good starting point. You are able to customize this to display images and the like but you'll have to do that in the platform-specific layout code.
Please note that I have only created the code for UWP and that should be enough to get you going for the other platforms.
I hope this helps somewhat.

Suppress WaitCursor for WinForms WebBrowser control

Consider the following simple WinForms form with a textbox and a webbrowser control. Whenever the textbox content changes, the text is pushed to the browser:
public class MainForm : Form
{
public MainForm()
{
var browser = new WebBrowser() { Dock = DockStyle.Fill };
var textbox = new TextBox() { Dock = DockStyle.Fill, Multiline = true };
var splitter = new SplitContainer() { Dock = DockStyle.Fill };
splitter.Panel1.Controls.Add(textbox);
splitter.Panel2.Controls.Add(browser);
this.Controls.Add(splitter);
textbox.TextChanged += delegate { browser.DocumentText = textbox.Text; };
textbox.Text = "<b>hello world</b>";
}
}
(I am doing something like this in my DownMarker code to build a Markdown editor with Stackoverflow's MarkdownSharp library.)
This works fine, except that the WebBrowser control insists on showing the wait cursor whenever DocumentText is set - even if updating the browser content takes only a few milliseconds. This results in mouse cursor flicker when typing in the textbox.
Is there any way to supress these mouse cursor changes? I already considered rate-limiting the DocumentText updates, but I find that the occasional flicker during an update is still annoying and I would prefer instant updates.
edit: Hans' answer pointed me in the right direction. Changing the TextChanged event handler to this seems to work without cursor flicker:
textbox.TextChanged +=
delegate
{
if (browser.Document == null)
{
browser.DocumentText = "<html><body></body></html>";
}
while ((browser.Document == null)
|| (browser.Document.Body == null))
{
Application.DoEvents();
}
browser.Document.Body.InnerHtml = textbox.Text;
};
edit2: the above still shows the wait cursor when the page is made heavier, e.g. by adding images. This might be fixable be doing more fine grained updates of just the html elements that change, but that is obviously much more complex.
Assigning the DocumentText property is a Big Deal, WebBrowser treats it like a navigation command. It can't tell the difference. Which normally takes time, hundreds of milliseconds, enough for it to justify displaying the wait cursor.
A very different approach would be to load a dummy document and alter the DOM through the Document property. That's pretty common in web pages, Ajax and javascript and what-not. No wait cursor for those. Not so sure if that will still fit your editing model, I'd guess at you wanting to load a dummy HTML document with a empty <body> and change the body content.
Should work. Back-up plan is an Update! button. Which would also avoid trying to render half-finished and thus broken HTML.

How do I change a display using TreeView?

I'm trying to change a panel to a specific form (as this is the only way I can fathom it) based on the selected TreeView node. For example, in Visual Studio, if you right-click on "Solution 'solutionname' (1 Project)", click 'Properties', it comes up with a tree list on the left side. When you click on a selection, the right pane changes.
I've searched continuously for hours the previous few days and only found a tutorial showing how it can affect a webBrowser control.
This is a farfetched example that I can understand:
private void tree_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
treeNode nName = e.Node;
//For testing:
string pg = "";
pg = nName.Tag;
if (pg == "Form2") display = Form2;
}
Display is a panel. I know this is absolutely wrong, but I couldn't find any proper method using my search terms.
You will need to set Visible on all your panels to false, except for the one you want to display which will be set to true.
WinForms does not have any particularly nice way of setting this up. You could set the Tag property of each node to be a reference to the panel (this has to be done programmatically - the designer won't let you do it), then iterate through the entire tree view to set ((Panel)node.Tag).Visible = false followed by ((Panel)e.Node.Tag).Visible = true or you can maintain the list separately. If you don't have many panels, a switch/if-else block may be okay, too.

Categories