I have a modal popup that can be dragged and moved. It also contains an ajaxUpdatePanel to update certain elements within it.
My problem is that if the modal popup has been moved around and the update panel fires, the popup will pop back to center position. Nothing breaks, it's just annoying to end users.
Any clues?
You may use script below:
var x = null;
var y = null;
Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(InitializeRequest);
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoaded);
function pageLoaded(sender, args) {
var extender = $find("ModalPopupExtender1"); // extender's BehaviorID
if (extender != null && x != null && y != null) {
extender.set_X(parseInt(x));
extender.set_Y(parseInt(y));
}
}
function InitializeRequest(sender, args) {
var extender = $find("ModalPopupExtender1"); // extender's BehaviorID
x = extender._foregroundElement.style.left;
y = extender._foregroundElement.style.top;
}
If you'll close popup and open it again without full postback it will save previous position, but the next time it will be centered again.
Related
I have a ListView (native) with dynamic content and I want to know how to detect when the user scrolls it, but not the style of "isScrolling = true/false", instead I want to know when the user scrolls it up, and when the user scrolls it down.
I tried this trick: https://stackoverflow.com/a/27294644/4668642
But the problem is that it's only return "true/false" (actually it's fires a Sub) and it floods the Sub too (I mean, I scroll the ListView very hard and the Sub is being fired multiple times, so the action it's being bugged).
I don't know if there is a Native way (Like an event as ManipulationDelta [it's doesn't works]) or another trick like that post.
This is my code for now:
'On a shared file'
Public Shared Function GetScrollViewer(depObj As DependencyObject) As ScrollViewer
If TypeOf depObj Is ScrollViewer Then
Return TryCast(depObj, ScrollViewer)
End If
For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(depObj) - 1
Dim child = VisualTreeHelper.GetChild(depObj, i)
Dim result = GetScrollViewer(child)
If result IsNot Nothing Then
Return result
End If
Next
Return Nothing
End Function
'on OnNavigatedTo event'
AddHandler GetScrollViewer(LVNot).ViewChanged, AddressOf LVNot_ViewChanged
'At the end of the Main.xaml.vb file'
Private Sub LVNot_ViewChanged()
If Cab.isUp = True Then
Cab.goDownSub()
End If
End Sub
Note1: "Cab" is a "Custom AppBar control" (UserControl), isUp is a boolean that return True when Cab is up (visible), and False when it's down (Hide), and goDownSub() is a Sub that Hide the "Cab"
Note2: This code is made with VB (VisualBasic), but I work with C# too. I don't have any problem with answerd made with C# instead of VB.
Hmm, cause listview itself contains a built in scroll viewer you can not put this control in another scroll viewer and get the scroll offset easily, my suggestion is to use a stack panel in a ScrollViwer and monitor the changes in event of ViewChanged of scrollViwer and get the currently offset by VerticalOffset() method.
Okey, I found a way to get the listview's position.
The follow code was extracted from https://stackoverflow.com/a/4954586/4668642
var scrollViewer = FindScrollViewer(listBox);
var offset = scrollViewer.VerticalOffset;
static ScrollViewer FindScrollViewer(DependencyObject parent)
{
var childCount = VisualTreeHelper.GetChildrenCount(parent);
for (var i = 0; i < childCount; i++)
{
var elt = VisualTreeHelper.GetChild(parent, i);
if (elt is ScrollViewer) return (ScrollViewer)elt;
var result = FindScrollViewer(elt);
if (result != null) return result;
}
return null;
}
Then it's possible to determinate which direction was the listview scrolling to:
Double offSetNew, offSetOld
private void LVNot_ViewChanged()
{
dynamic ScrollViewer = FindScrollViewer(LVNot);
offSetNew = ScrollViewer.VerticalOffset;
if (offSetOld != 0) { //To avoid (offSetOld > offSetNew) being fired in the first instance
if (offSetOld > offSetNew) {
//Go Up
} else if (offSetOld < offSetNew) {
//Go Down
}
}
offSetOld = offSetNew;
}
Right, so I have 13 textboxes with corresponding labels that are assigned after a user decides the name from a different form (instantiated by the 'Add field...' button). The issue arises when the user wishes to delete a textbox with previously entered data, as this results in an empty space where the textbox and label originally were as visualized by the following image:
My question is: how do I make it so that when a user chooses to delete a textbox, the textbox-label pair(s) that follow it replace the deleted textbox AND shift the remaining textboxes accordingly.
Textbox-label pairs in designer:
I've thought about this problem intensively over the past few days, and have concluded that with my current knowledge of C# I am limited to solving this issue with a horrendously tedious amount of if-statements (talking hundreds - thousands here). Any and all help would be appreciated!
Current code on the X-button for first textbox-label pair:
private void xButton1_Click(object sender, EventArgs e)
{
label14.Text = "";
textBox1.Text = "";
if (label14.Text.Equals(""))
{
label14.Visible = false;
textBox1.Visible = false;
xButton.Visible = false;
label14.Text = "";
textBox1.Text = "";
}
if (!textBox2.Text.Equals(""))
{
label14.Text = label15.Text;
textBox1.Text = textBox2.Text;
}
if (!textBox2.Text.Equals("") && (textBox3.Text.Equals("")))
{
label15.Visible = false;
textBox2.Text = "";
textBox2.Visible = false;
xButton2.Visible = false;
}
}
One simple thing you could do is give all your "dynamic" controls (label, textbox, button) a similar value in their Tag property (in my example, I used the string "dynamic" for all the control Tags. This enables you to query for them easily.
Next, you could follow the logic that, anytime you delete some controls, you move all controls below the deleted ones up a distance equal to the height of the control being deleted plus whatever padding you have between the controls.
For example, when a user clicks the X button, since you know the value of the Bottom of the control that's being deleted, you could find all controls that had a matching Tag property whose Top is greater than the x button Bottom, and you can move them up.
Here's an example (this assumes that all your X buttons are mapped to this same click event):
private void buttonX_Click(object sender, EventArgs e)
{
// This is represents the distance between the bottom
// of one control to the top of the next control
// Normally it would be defined globally, and used when you
// lay out your controls.
const int controlPadding = 6;
var xButton = sender as Button;
if (xButton == null) return;
var minTopValue = xButton.Bottom;
var distanceToMoveUp = xButton.Height + controlPadding;
// Find all controls that have the Tag and are at the same height as the button
var controlsToDelete = Controls.Cast<Control>().Where(control =>
control.Tag != null &&
control.Tag.ToString() == "dynamic" &&
control.Top == xButton.Top)
.ToList();
// Delete the controls
controlsToDelete.ForEach(Controls.Remove);
// Get all controls with the same tag that are below the deleted controls
var controlsToMove = Controls.Cast<Control>().Where(control =>
control.Tag != null &&
control.Tag.ToString() == "dynamic" &&
control.Top > minTopValue);
// Move each control up the specified amount
foreach (var controlToMove in controlsToMove)
{
controlToMove.Top -= distanceToMoveUp;
}
}
How can I create progress update control programmatically in a c# non visual web part in Sharepoint?
I am using c# and the goal is to creates a text of "Loading..." inside the ProgressUpdate control that becomes visible while the update panel is loading more content and then disappears when content is loaded. If anyone can help that would be awesome. I tried the following, but no luck. A button triggers the update panel and the update works well, but when I try to add an update progress it gets added into the page, but it never appears when I click my button that triggers the update.
UpdatePanel up = new UpdatePanel();
up.UpdateMode = UpdatePanelUpdateMode.Always;
up.ID = "Panel1";
UpdateProgress upp1 = new UpdateProgress();
upp1.AssociatedUpdatePanelID = up.ID.ToString();
upp1.ID = "UpdateProgress1";
upp1.Controls.Add(new LiteralControl("<p>Loading...</p>"));
Controls.Add(upp1);
Alright so here is what I have found. If you make an Update Progress control outside an Update Panel, then it will fail to be able to listen to the trigger on the update panel when it fires. More can be read about that at the link below.
http://www.mostlydevelopers.com/blog/post/2008/08/23/Show-UpdateProgress-when-using-an-UpdatePanel-with-Triggers.aspx
So since I'm doing it this way, I had to use a javascript work around. I had to use the getInstance() method of the PageRequestManager object to get the instance of the PageRequestManager class. I then added the functions for the asynchronous request when it is initialized and ends. This will allow us to show our UpdateProgress control when an Asynchronous call begins and ends. (See Javascript Below)
//Function for postbackUpdateProgress
var prm = Sys.WebForms.PageRequestManager.getInstance();
var postBackElement;
function CancelAsyncPostBack() {
if (prm.get_isInAsyncPostBack()) {
prm.abortPostBack();
}
}
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
function InitializeRequest(sender, args) {
if (prm.get_isInAsyncPostBack()) {
args.set_cancel(true);
}
//Get the element that asynchronous postback
postBackElement = args.get_postBackElement();
//check to see if any of the following controls activate sender request.
//search is used to search for the ID name in the string that sharepoint spits out
// as the ID.
var controlA = postBackElement.id.search("DropDownListType");
var controlB = postBackElement.id.search("UserProfileDropList");
var controlC = postBackElement.id.search("MoreNewsLinkButton");
var controlD = postBackElement.id.search("PreviousNewsLinkButton");
if (controlA != -1 || controlB != -1 || controlC != -1 || controlD != -1) {
$('*[id*=Panel1]:visible').hide();
//show UpdateProgress
$('*[id*=UpdateProgress1]').show();
}
}
//After async postback complete, then show panel again and hide UpdateProgress
function EndRequest(sender, args) {
$('*[id*=Panel1]').show();//use wild card in jquery to find Panel1 ID
$('*[id*=UpdateProgress1]:visible').hide();
}
Please note that I had to do a search() for the ID name because sharepoint puts a bunch of text before your ID name and javascript would otherwise not be able to find it by the text literal of the ID alone. A wild card approach with jquery is used to find the panel by using:
$('[id=Panel1]').show();//use wild card in jquery to find Panel1 ID
to show it.
and
$('[id=Panel1]:visible').hide();
to hide the update panel when the async call is initialized. You don't have to hide the update panel, but my particular implementation looks more aesthetically pleasing if I do.
My webbrowser control has to be disabled (enabled = false) so that the user can't click in it.
This also disables the access to the scrollbar so I'm thinking about creating another scrollbar next to the control that gets and passes its values from and to the webbrowser's scrollbar.
For that, I need to access the webbrowser scrollbar control. How can I find it ?
webbrowser.Controls.Count returns zero.
Hmm I don't know if there is any method to acccess the scrollbar position programmaticly. You can however, scroll by element name:
private void ScrollToElement(String elemName)
{
if (webBrowser1.Document != null)
{
HtmlDocument doc = webBrowser1.Document;
HtmlElementCollection elems = doc.All.GetElementsByName(elemName);
if (elems != null && elems.Count > 0)
{
HtmlElement elem = elems[0];
elem.ScrollIntoView(true);
}
}
}
Also, see this question for other possibilities.
EDIT:
See question Scrolling WebBrowser programatically sometimes doesn't work
How can you scroll to the top of a web broswer control. The page I am loading has an iframe and the scroll bar is starting 20px down. It only happens in my application. I would like to auto scroll to the top.
Quick search yields: webBrowser1.Document.Window.ScrollTo(0, 200);
If what you mean is wanting to scroll the content of the iframe to the top, the following should help.
First you will need 2 things:
Add reference to C:\Program Files\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll
edit your <iframe> tag so that it has an id, eg: id="something"
Finally, the code:
HtmlElement ele = webBrowser1.Document.GetElementById("something");
mshtml.HTMLIFrameClass frame = ele.DomElement as mshtml.HTMLIFrameClass;
if (frame != null)
{
mshtml.HTMLDocumentClass doc = frame.document as mshtml.HTMLDocumentClass;
if (doc != null)
{
object i = 0;
mshtml.HTMLWindow2Class win = doc.frames.item(ref i) as mshtml.HTMLWindow2Class;
if(win != null)
win.scrollTo(0, 0);
}
}