I have MSChart control within Panel in my form. Panel has AutoScroll property set to True. Once the chart gets too big - user is able to scroll through it.
Once user presses Ctrl+MouseWheel I am enabling zoom in/out to the chart area. Currently on MouseWheel - both Panel and Chart are scrolling. How do I disable Panel scrollbars at the time when Chart is handling scrolling events?
After disabling AutoScroll property Panel is moving scroll to the top and hiding vertical scrollbar - so this is not what I want:
void Chart_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control == true)
{
(Parent as Panel).AutoScroll = false;
}
}
void Chart_KeyUp(object sender, KeyEventArgs e)
{
if (e.Control == false)
{
(Parent as Panel).AutoScroll = true;
}
}
I would like Panel scrollbar to "freeze" when chart is zooming (ctrl+mousewheel) and activate when chart is idle (mousewheel). Any ideas?
Related
In my WinForm project I have panel control and it has DataGridview child. Datagridview has 50 columns and this needs scrolling. but i don't want to use Datagridview scroll bar. I want to use panel scroll bar.
But these two scrollbar has different functionalities. Datagridview scrollbar has more capabilities than panel scroll bar.
For example,
1)With DatagirdView scrollbar you can freeze columns easily.
2)Also while entering data in datagridview, with TAB key, scrollbars move automatically.
Is there any solution to add Datagridview scroll bar functions to panel scrollbar's.
Or How to add the above 2 functions to panel scrollbar.
Thanx in advance.
The panel scrollbar can only be used to control the position of the entire datagridview.
Here is a workaround that using external Scrollbar to scroll datagridview.
First, need to add a HScrollBar to the form and set its properties as followed.
hScrollBar1.Maximum = dataGridView1.Columns[0].Width * dataGridView1.ColumnCount + dataGridView1.RowHeadersWidth;
hScrollBar1.Value = 0;
hScrollBar1.Location = new Point(panel1.Location.X, panel1.Location.Y + panel1.Height);
And subscribe to Scroll event
hScrollBar1.Scroll += hScrollBar_Scroll;
private void hScrollBar_Scroll(object sender, ScrollEventArgs e)
{
int rowindex = dataGridView1.CurrentCell.RowIndex;
int columnindex = (hScrollBar1.Value - dataGridView1.RowHeadersWidth) / dataGridView1.Columns[0].Width;
this.dataGridView1.CurrentCell = this.dataGridView1[columnindex, rowindex];
}
If want to change the scrollbar value according to the selected cell, subscribe to DataGridView.SelectionChanged event.
dataGridView1.SelectionChanged += dataGridView_SelectionChanged;
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
hScrollBar1.Value = (dataGridView1.CurrentCell.ColumnIndex + 1) * dataGridView1.Columns[0].Width + dataGridView1.RowHeadersWidth;
}
The above columnindex and hScrollBar1.Value are obtained according to the following formula:
I have a UserControl within a WinForms-form where within is a panel that resizes its content by custom code when the parent window is resized:
private void ResizeElements(FlowLayoutPanel panel) {
panel.SuspendLayout();
foreach (Control ctrl in panel.Controls) {
ctrl.Width = panel.ClientSize.Width - 20;
}
panel.ResumeLayout();
}
private void flowPanel_Resize(object sender, EventArgs e) {
ResizeElements((FlowLayoutPanel)sender);
}
This works just fine when I resize the window manually by grabbing it at the lower right corner and resize there:
This does not work however, wenn I maximize the window and after that click onto the restore-controlbox between minimize and maximize.
The controls from that Panel seem to have the right width, but the FlowLayoutPanel that contains them has a horizontal scrollbar:
When I resize the window manually again the horizontal scrollbar disappears and everything is as expected.
The flowpanel has DockingStyle.Fill
Update: I currently do the following to get around this issue:
private void frmMain_Resize(object sender, EventArgs e)
{
var oldWindowState = _previousWindowState;
_previousWindowState = this.WindowState;
if (oldWindowState == FormWindowState.Maximized && this.WindowState == FormWindowState.Normal)
{
this.Width++;
this.Width--;
}
}
So I resize manually when detecting a restore-click forcing the correct events to be fired. I am fully aware that this is an evil hack and still would prefer a more clean solution.
(Update): Parent Controls:
WinForm
->Panel Dock: Fill, AutoSize: false
->UserControl Dock: Fill, AutoSize: false
->TabControl Dock: Fill
->Tab
->FlowLayoutPanel Dock: Fill, AutoSize: false
I'm developing a windows forms application. And i have the following issue: in a form there's a panel, and in that panel i have a number of controls (just a label with a text box, the number is determined at runtime). This panel has a size that is smaller than the sum of all the controls added dynamically. So, i need a scroll. Well, the idea is: when the user open the form: the first of the controls must be focused, the the user enters a text and press enter, the the next control must be focused, and so until finished.
Well it's very probably that not all the controls fit in the panel, so i want that when a control inside the panel got focus the panel scrolls to let the user see the control and allow him to see what he is entering in the text box.
I hope to be clear.
here is some code, this code is used to generated the controls and added to the panel:
List<String> titles = this.BancaService.ValuesTitle();
int position = 0;
foreach (String title in titles)
{
BancaInputControl control = new BancaInputControl(title);
control.OnInputGotFocus = (c) => {
//pnBancaInputContainer.VerticalScroll.Value = 40;
//pnBancaInputContainer.AutoScrollOffset = new Point(0, c.Top);
// HERE, WHAT CAN I DO?
};
control.Top = position;
this.pnBancaInputContainer.Controls.Add(control);
position += 10 + control.Height;
}
If you set AutoScroll to true this will be taken care of automatically. As for the idea that Enter should move focus to next field, the best solution would be to execute enter as if it was TAB key in BancaInputControl:
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.KeyCode == Keys.Enter)
{
e.Handled = true;
// Move focus to next control in parent container
Parent.SelectNextControl(this, true, true, false, false);
}
}
If BancaInputControl is composite control (a UserControl containing other controls) each child control should hook up KeyDown event to this handler. It tries to move focus to next control in BancaInputControl; if it fails, moves focus to parent container's next control.
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
e.Handled = true;
if (!SelectNextControl((Control)sender, true, true, false, false))
{
Parent.SelectNextControl(this, true, true, false, false);
}
}
}
Here is the situation:
I am trying to control flowLayoutControl's scroll bar from devexpress controls VerticalScroll.
Now - flowLayoutControl with autoscroll = true. I added a new verticalscroll control and dock it to Right. So now the Devexpress Vertical Scroll control is right on top of FlowLayout scrollbar.
Also the FlowLayoutPanel vertical scroll does not hide when following code is run:
spotWinFlowLayout1.VerticalScroll.Visible = false
I have setup the following event handlers:
private void spotWinFlowLayout1_Resize(object sender, EventArgs e)
{
SetupVerticalScrollBar();
}
private void SetupVerticalScrollBar()
{
vScrollBar1.Minimum = spotWinFlowLayout1.VerticalScroll.Minimum;
vScrollBar1.Maximum = spotWinFlowLayout1.VerticalScroll.Maximum;
vScrollBar1.LargeChange = spotWinFlowLayout1.VerticalScroll.LargeChange;
vScrollBar1.SmallChange = spotWinFlowLayout1.VerticalScroll.SmallChange;
}
private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
{
spotWinFlowLayout1.VerticalScroll.Value = e.NewValue;
}
Everything is working fine except when on form Load there is already a scrollbar on flowLayoutControl,
spotWinFlowLayout1.VerticalScroll.XXX properties not set yet. So both the scrollbars are out of Sync. But as soon as I resize the form both get Sync.
So when is scrollbar for the FlowLayoutPanel initialized?
So when is scrollbar for the
FlowLayoutPanel initialized?
This might sound like a smartalec answer: "When the control is drawn or placed on the form" which is the reason when you adjust the size of the form they are in sync.( they are being drawn again )
The solution is to manually add the scrollbars yourself.
Is there a way to detect if the scrollbar from the ScrollViewer in a ListView has reached the bottom of the virtual scroll space? I would like to detect this to fetch more items from the server to put into the bound ObservableCollection on the ListView.
Right now I'm doing this:
private void currentTagNotContactsList_scrollChanged(object sender, ScrollChangedEventArgs e) {
ListView v = (ListView)sender;
if (e.VerticalOffset + e.ViewportHeight == e.ExtentHeight) {
Debug.Print("At the bottom of the list!");
}
}
Is this even correct? I also need to differentiate between the vertical scrollbar causing the event and the horizontal scrollbar causing it (i.e. I don't want to keep generating calls to the server if you scroll horizontally at the bottom of the box).
Thanks.
//A small change in the "Max's" answer to stop the repeatedly call.
//this line to stop the repeatedly call
ScrollViewer.CanContentScroll="False"
private void dtGrid_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
//this is for vertical check & will avoid the call at the load time (first time)
if (e.VerticalChange > 0)
{
if (e.VerticalOffset + e.ViewportHeight == e.ExtentHeight)
{
// Do your Stuff
}
}
}
I figured it out. It seems I should have been getting events from the ScrollBar (<ListView ScrollBar.Scroll="currentTagNotContactsList_Scroll" in XAML) itself, rather than the viewer. This works, but I just have to figure a way to avoid the event handler being called repeatedly once the scrollbar is down. Maybe a timer would be good:
private void currentTagNotContactsList_Scroll(object sender, ScrollEventArgs e) {
ScrollBar sb = e.OriginalSource as ScrollBar;
if (sb.Orientation == Orientation.Horizontal)
return;
if (sb.Value == sb.Maximum) {
Debug.Print("At the bottom of the list!");
}
}
For UWP I got it like this
<ScrollViewer Name="scroll" ViewChanged="scroll_ViewChanged">
<ListView />
</ScrollViewer>
private void scroll_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
var scrollViewer = (ScrollViewer)sender;
if (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight)
btnNewUpdates.Visibility = Visibility.Visible;
}
you can try this way:
<ListView ScrollViewer.ScrollChanged="Scroll_ScrollChanged">
and in Back:
private void Scroll_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
// Get the border of the listview (first child of a listview)
Decorator border = VisualTreeHelper.GetChild(sender as ListView, 0) as Decorator;
// Get scrollviewer
ScrollViewer scrollViewer = border.Child as ScrollViewer;
if (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight)
Debug.Print("At the bottom of the list!");
}
Not recommand to use ScrollBar.Scroll , beacause if you scroll the middle wheel of the mouse, it won't work.
ScrollBar.Scroll="currentTagNotContactsList_Scroll"
The following support both right side scroll bar and mouse's wheel scroll.
in listbox's xmal:
ScrollViewer.ScrollChanged="ScrollViewer_ScrollChanged"
in c#:
private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
var listBox = (ListBox)sender;
var scrollViewer = (ScrollViewer)VisualTreeHelper.GetChild(listBox, 0);
if (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight)
{
Console.WriteLine("____At the bottom of the list!");
}
}