I am using a RadTreeView control from telerik.
I am binding data to my tree using hierarchical data templates.
The data is displaying fine but when I programmatically expand all my items tree is scrolling horizontally right to the furthest point.
I have tried hooking into the loaded event of the tree view and only enabling horizontal scrollbar after the expand all has been called but this doesn't work.
private void FrameworkElement_OnLoaded(object sender, RoutedEventArgs e)
{
var rtv = sender as RadTreeView;
if (rtv.ScrollViewer != null)
{
rtv.ScrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
rtv.ExpandAll();
System.Windows.MessageBox.Show("test"); //this causes desired behaviour.
rtv.ScrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
}
}
One thing I have noticed is if I add a call to show a messagebox after the expandall call the horizontal scroll bar is displayed scrolled to the left as required.
Is the messagebox causing the UI to fully refresh and expand before enabling the scrollbar?
Please let me know if you need anymore information.
Related
I have a ChartControl inside a Grid where there is a ScrollViewer.
I need to activate zoom on the ChartControl but when I use the mouse wheel on the ChartControl, until I reach the limit on the Grid ScrollViewer, it's the Grid ScrollViewer who is scrolling instead.
I think there is something missing inside the DevExpress control because on the native WPF control it's working. Example list view below.
ChartControl cc = new ChartControl();
cc.Titles.Add(new DevExpress.Xpf.Charts.Title() { Content = "" });
cc.Legend = new DevExpress.Xpf.Charts.Legend();
DevExpress.Xpf.Charts.XYDiagram2D xy = new DevExpress.Xpf.Charts.XYDiagram2D();
xy.EnableAxisXNavigation = true;
xy.EnableAxisYNavigation = true;
To resolve this issue, implement custom mouse wheel processing by handling the ScrollViewer.PreviewMouseWheel event. Check
this ticket for a sample project illustrating this approach (see the DXSample.zip archive).
I have a grid/panel on my UI that can take a drop action. The control is a Grid with some dynamically created content in it (a viewbox containing a stack panel of borders if that matters).
When I drag relevant information into the grid I want it to change (regenerate) the internal content and when it drops or leaves it should go back to normal. I have the 'change it' and 'put it back' methods working just fine, but I'm having trouble determining when to call them.
I have drag enter and drag leave events on the grid. The enter works great, but the leave is not. As soon as the mouse gets over the top of the content inside of the grid it fires a drag leave event, so it changes the content (and if that puts it back out of the child content it fires the drag enter again and just flashes).
My first thought was to just determine if the mouse is actually still over the grid and just ditch out without putting the content back. However this doesn't seem to be working. Here is my code for drag leave:
private void Grid_DragLeave(object sender, DragEventArgs e)
{
var wizard = DataContext as WizardVM;
var gd = sender as Grid;
if (wizard == null || gd == null || gd.IsMouseOver ||
gd.Children.Cast<FrameworkElement>().Any(x => x.IsMouseOver)) return;
wizard.Assembly.CollapsePreview();
}
As you can see, I even tried to iterate the children of the grid and see if mouse over is true on any of those and ditch out, and still it just keeps returning false for all of that and collapsing. I thought IsMouseOver was supposed to tell me if the mouse is over at all even if it's children of the control...
Ok well after some more research I found something that seems to be working. I ended up having to use VisualTreeHelper.HitTest and use the overload that has a callback and gets all hit items even if it's obscured. Here is my final code:
void Grid_DragLeave(object sender, DragEventArgs e)
{
var wizard = DataContext as WizardVM;
var gd = sender as Grid;
if (wizard == null || gd == null) return;
Point pt = e.GetPosition(this);
hitResults.Clear();
VisualTreeHelper.HitTest(gd, null, GridHitTestResultCallback,
new PointHitTestParameters(pt));
if (!hitResults.Contains(gd))
{
wizard.Assembly.IsExpanded = false;
}
}
HitTestResultBehavior GridHitTestResultCallback(HitTestResult result)
{
hitResults.Add(result.VisualHit);
return HitTestResultBehavior.Continue;
}
Basically it gets the point in relation to the full window, then calls HitTest with that point and the overall grid I'm trying to work with. The callback populates a list of visuals that are hit by the hit test. Last the original method checks if the grid is in the list of hits and if not it collapses it.
As a side note I also changed from .ExpandPreview() and .CollapsePreview() methods to a .IsExpanded property for unrelated reasons... didn't want anyone to be confused by that change...
Let's just say that I have many controls on my Form, and when a User clicks on one of them, its height will expand. This means that, currently, when this clicked-control expands, other controls below it will become overlapped by the expanded control.
But what I want to happen, is for each Control below the expanded control to slide down, so that they are below the expanded control again.
I know how to handle sliding, but I just don't know how to make every control except for one move everytime a given control is moved.
Any help at all is greatly appreciated, thank you!
This is what I was thinking:
void newOrderReceived(object sender, EventArgs e)
{
foreach(Control OrderNotificationBox in OrdersPanel.Controls)
{
if(OrderNotificationBox is NotificationBox) // Checks to see if the control is a NotificationBox
{
// Add my code to slide controls down.
}
}
}
But... How do I know if the control is below the expanded control?
Is this how I should go about changing the location of all controls below the expanded control?
Edit: Just had a thought, to check to see if a NotificationBox is below the Expanded NotificationBox, see revised code below:
void newOrderReceived(object sender, EventArgs e)
{
foreach(Control OrderNotificationBox in OrdersPanel.Controls)
{
if(OrderNotificationBox is NotificationBox) // Checks to see if the control is a NotificationBox
{
if(OrderNotificationBox.Location.Y <= ExpandedNotificationBox.Location.Y + ExpandedNotificationBox.Size.Width)
{
// Add my code to slide controls down.
}
}
}
}
But would this be sufficient? Currently, this is working, so I guess I just answered my own question. But, isn't there a better way to do this? A more elegant/efficient way?
Here's a sample of how it should look:
FlowLayoutPanel provides you with dynamic layout where you can resize any control in it and all below controls will slide automatically. There are many strategies to using groups/columns of flow layout panels to be able to achieve the desired look for the whole form. Some googling will reveal some of these.
For instance in the form above, resizing the button1 control simply flows all the below controls to further down on the form. You can try that at the design time also. Drop the form a flow layout panel, drop 3-4 control in the container and start experimenting..
For each expandable content use Panel.
Dock your panels one under another (Use panel1.Dock = DockStyle.Top. For the very bottom panel use panel1.Dock = DockStyle.Fill).
Place your child controls inside of each expandable panel, set inner controls' Anchor properties accordingly.
When you expand one panel, the rest of the panels will adjust automatically. You don't need to code for this. You will only change Height of a panel that you currently expand.
What you need is some kind of 'ExplorerBar' functionality. There are several control libraries that offer that, and I found the article here on the CodeProject that has it for free.
i have a panel in my winforms and in it i load some usercontrols .
i would like to autoscroll to the bottom of the panel( as my panel fills ) everytime a new usercontrol is added . How can i do so ?
You can do that by setting the VerticalScroll of the Panel but I think it would be better to use ScrollControlIntoView instead.
private void panel1_ControlAdded(object sender, ControlEventArgs e)
{
panel1.ScrollControlIntoView(e.Control);
}
Good luck!
You could use ScrollControlIntoView and pass the control you last added.
An alternate solution would be:
panel.VerticalScroll.Value = panel.VerticalScroll.Maximum
I found that continuously adding controls to the panel at vertical increments would be affected negatively whenever a user had scrolled the panel up or down. I used the tip from Homam above, and found the following to work well:
panel1.VerticalScroll.Value = 0;
// Creating and adding a TextBox, tb, to the panel
panel1.ScrollControlIntoView(tb);
So first, I scroll to the top in order to use absolute vertical positions for my text boxes, then I place the Text Box, and finally, I make sure that the newly created text box comes into view.
I created a custom DataGridViewCell to show a specific UserControl when the user starts editing the cell. Basically the control contains a TextBox with a suggestion list easily handled by the code.
I got my code to resize the list correctly, and have it contain exactly what I want and where I want it. The problem I have now is that the control is not being drawn correctly on the screen, and the ListBox is probably beind drawn "inside" the row, and since it is much higher than the row, does not get shown on screen.
How can I make the control draw on top of the DataGridView?
You'll probably need to put the ListBox in a separate popup form. Good luck.
Alternatively, you can put the ListBox in the GridView's parent form, then call BringToTop to make sure it's on top of the grid view.
There's a msdn article, Build a Custom NumericUpDown Cell and Column for the DataGridView Control, that paints custom controls on datagridviews. The code sample provided there might help solve your problem.
I think you'll want to take a look at Faking alternative controls within a DataGridView control in Win Forms 2.0. It will look like the control is hosted within the DataGridView, but in actuality it is just positioned nicely over the cell. I am using this now for two DateTimePickers and one ComboBox with great success.
Sample code from link:
protected void dgCategory_CellClick(object sender, DataGridViewCellEventArgs e)
{
//set Date Picker to false when initially click on cell
if (dtPicker.Visible)
dtPicker.Visible = false;
if (e.ColumnIndex == 2)
{
//set date picker for category datagrid
dtPicker.Size = dgCategory.CurrentCell.Size;
dtPicker.Top = dgCategory.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true).Top;
dtPicker.Left = dgCategory.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true).Left;
if (!(object.Equals(Convert.ToString(dgCategory.CurrentCell.Value), "")))
dtPicker.Value = Convert.ToDateTime(dgCategory.CurrentCell.Value);
dtPicker.Visible = true;
}
}
private void dtPicker_ValueChanged(object sender, EventArgs e)
{
dgCategory.CurrentCell.Value = dtPicker.Value;
dtPicker.Visible = false;
}