How to have android like scrollbars for my WPF ListView. I mean to say, the scrollbar should be visible only when the user scrolls. They should fade out as soon as the user stops scrolling. How to achieve this?
You can use the DispatcherTimer class from the System.Windows.Threading namespace.
Here is the XAML markup for your window:
<Window x:Class="testwpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ListView Name="list" ScrollViewer.VerticalScrollBarVisibility="Hidden" Loaded="list_Loaded">
</ListView>
</Window>
And here is the code behind:
public partial class MainWindow : Window
{
DispatcherTimer dispatcherTimer;
public MainWindow()
{
InitializeComponent();
dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += dispatcherTimer_Tick;
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
// we are here only if for the last 500 ms there were no changes of
// the scrollbar's vertical offset and we can hide a scrollbar
list.SetValue(ScrollViewer.VerticalScrollBarVisibilityProperty, ScrollBarVisibility.Hidden);
dispatcherTimer.Stop();
}
private void list_Loaded(object sender, RoutedEventArgs e)
{
// attach a handler
Decorator border = VisualTreeHelper.GetChild(list, 0) as Decorator;
ScrollViewer scroll = border.Child as ScrollViewer;
scroll.ScrollChanged += list_ScrollChanged;
}
private void list_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
// when vertical scroll position is changed, we set VerticalScrollBarVisibilityProperty
// to Auto (scroll bar is displayed only if needed) and run a timer with 500 ms interval
if (e.VerticalChange != 0)
{
list.SetValue(ScrollViewer.VerticalScrollBarVisibilityProperty, ScrollBarVisibility.Auto);
dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);
dispatcherTimer.Start();
}
}
}
This is a raw example. Of course, you can apply your own conditions defining whether you should hide a scrollbar. For example, you might decide not to hide a scrollbar if left mouse button is still pressed over a scrollbar.
Related
I'm using this code to lower window's opacity when user moving it and after drag move is completed i'm incresing window's opacity to it's original value.
private void TopBar_Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
var decreaseOpacityAnim = new DoubleAnimation(0.5, (Duration)TimeSpan.FromSeconds(1));
this.BeginAnimation(UIElement.OpacityProperty, decreaseOpacityAnim);
this.DragMove();
var increaseOpacityAnim = new DoubleAnimation(1, (Duration)TimeSpan.FromSeconds(1));
this.BeginAnimation(UIElement.OpacityProperty, increaseOpacityAnim);
}
}
The problem is when user started to move window and the time window's opacity decreasing, window moves stutter. When animation completed window starts moving without stuttering.
Is there anything i can do to fix this?
I handled MouseMove instead of MouseDown. And secondly, you are using both animations while dragging, hence this stutter. Below code works absolutely fine for me.
<Window ...>
<Grid Background="Yellow" MouseMove="Grid_MouseMove_1"/>
</Window>
Code :
private bool animation_is_running = false;
private void Grid_MouseMove_1(object sender, MouseEventArgs e)
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
if (!animation_is_running)
{
var decreaseOpacityAnim = new DoubleAnimation(0.5, (Duration)TimeSpan.FromSeconds(1));
this.BeginAnimation(UIElement.OpacityProperty, decreaseOpacityAnim);
animation_is_running = true;
}
this.DragMove();
}
else
{
if (animation_is_running)
{
var increaseOpacityAnim = new DoubleAnimation(1, (Duration)TimeSpan.FromSeconds(1));
this.BeginAnimation(UIElement.OpacityProperty, increaseOpacityAnim);
animation_is_running = false;
}
}
}
I'm working with WPF 4 and VB.net 2010. My project consists of full-screen windows with a 640x480 grid in the center.
In this project, I want to have various image boxes (which will have the item .png images in them), that the user can drag around and drop in various places on the grid.
In essence, I need to be able to make it possible for the item to be clicked and dragged around the grid, with the image box still visible and the same size as the user moves it around. It should never be able to leave the grid. I also need to be able to determine if the object is over another object, so when the mouse button is released, the dragged object is "dropped", and it triggers a particular block of code.
How do I do this?
Something similar to your 'project', but using C#
From http://pastie.org/1498237
// XAML
<Window x:Class="MyProject.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="500" Width="500">
<Grid>
<Canvas x:Name="mycanv">
<Image Width="150" x:Name="myimg" Source="some_source.png"/>
</Canvas>
</Grid>
</Window>
//C#
private Point mouseClick;
private double canvasLeft;
private double canvasTop;
public Window1()
{
InitializeComponent();
foreach (object obj in mycanv.Children)
{
try
{
Image img = (Image)obj;
img.PreviewMouseDown += new MouseButtonEventHandler(myimg_MouseDown);
img.PreviewMouseMove += new MouseEventHandler(myimg_MouseMove);
img.PreviewMouseUp += new MouseButtonEventHandler(myimg_MouseUp);
img.TextInput += new TextCompositionEventHandler(myimg_TextInput);
img.LostMouseCapture += new MouseEventHandler(myimg_LostMouseCapture);
img.SetValue(Canvas.LeftProperty, 0.0);
img.SetValue(Canvas.TopProperty, 0.0);
}
catch
{
//do something
}
}
}
void myimg_LostMouseCapture(object sender, MouseEventArgs e)
{
((Image)sender).ReleaseMouseCapture();
}
void myimg_TextInput(object sender, TextCompositionEventArgs e)
{
((Image)sender).ReleaseMouseCapture();
}
void myimg_MouseUp(object sender, MouseButtonEventArgs e)
{
((Image)sender).ReleaseMouseCapture();
}
void myimg_MouseMove(object sender, MouseEventArgs e)
{
if (((Image)sender).IsMouseCaptured)
{
Point mouseCurrent = e.GetPosition(null);
double Left = mouseCurrent.X - canvasLeft;
double Top = mouseCurrent.Y - canvasTop;
((Image)sender).SetValue(Canvas.LeftProperty, canvasLeft + Left);
((Image)sender).SetValue(Canvas.TopProperty, canvasTop + Top);
canvasLeft = Canvas.GetLeft(((Image)sender));
canvasTop = Canvas.GetTop(((Image)sender));
}
}
void myimg_MouseDown(object sender, MouseButtonEventArgs e)
{
mouseClick = e.GetPosition(null);
canvasLeft = Canvas.GetLeft(((Image)sender));
canvasTop = Canvas.GetTop(((Image)sender));
((Image)sender).CaptureMouse();
}
In WPF, how do I display a grabber (the mall dotted triangle in the lower right corner) in a StatusBar control? Thanks.
The grabber is on the top level window, not a property on the statusbar.
<Window x:Class="msbuildrefactor.MainWindow"
...
ResizeMode="CanResizeWithGrip">
The code below will work with or without a StatusBar control.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
this.ResizeMode = ResizeMode.CanResizeWithGrip;
}
}
I have a TreeView that launches a new window when each of its TreeViewItems Selected event is raised.
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"
Height="300"
Width="300">
<Grid>
<TreeView Name="treeView1">
<TreeViewItem Header="Root">
<TreeViewItem Header="Parent" Selected="ParentTreeViewItem_Selected">
<TreeViewItem Header="Child" Selected="TreeViewItem_Selected" ></TreeViewItem>
</TreeViewItem>
</TreeViewItem>
</TreeView>
</Grid>
</Window>
Code Behind
namespace WpfApplication1
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void TreeViewItem_Selected(object sender, RoutedEventArgs e)
{
Window w = new Window();
w.Show();
e.Handled = true;
}
private void ParentTreeViewItem_Selected(object sender, RoutedEventArgs e)
{
}
}
}
When I click on the child node the new window is launched as expected. However imediatly afterwords its parents Selected eventis fired stealing focus from the new window, and marking the parent node as the current selection!
My expectation was that the newly launched window would have focus, and the node that was clicked would turn gray indicating to the users his/hers selection. Does anyone have any idea of why this happens and how I can prevent it?
Thanks,
Brette
Thought I would post the answer. I finally found a way around this. Setting w.Owner = this; has no effect. Turns out launching a new window on the Selected event of a TreeViewItem causes some focus issues. I have not found out what the root cause is by executing this on the Dispatcher seems to correct it. See Below
private void ChildTreeViewItem_Selected(object sender, RoutedEventArgs e)
{
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => new Window().Show()));
}
Hope this saves someone else some time.
Brette
Add:
w.Owner = this
Example:
private void TreeViewItem_Selected(object sender, RoutedEventArgs e)
{
Window w = new Window();
w.Owner = this;
w.Show();
e.Handled = true;
}
How can focus the controls when select a tabitem in a tabcontrol?
You should capture the Selection changed event of the TabControl and inside that you focus the control you need. Just as
private void TabControl1_SelectionChanged(object sender, EventArgs e)
{
control1.Focus();
}
Not sure I understand what you're asking completely, but you probably want to capture the SelectionChanged event for the TabControl:
public Window1()
{
InitializeComponent();
TabControl1.SelectionChanged += TabControl1_SelectionChanged;
}
private void TabControl1_SelectionChanged(object sender, EventArgs e)
{
TabItem item = (TabItem)TabControl1.SelectedItem;
// Find the first control in the TabItem content and focus it?
}