I have a Ribbon with two tabs and one of the tabs contains a listbox, with auto-generated content.
I would like the mouse wheel to scroll through the listbox content and have tried lots of things, but the mouse wheel only ever switches Ribbon tabs.
Below is one solution I have tried where I attempt to release mouse the mouse control from the Ribbon and give it to the ListBox but, so far I have been unsuccessful. Is there a proper way to do this? Am I missing something?
xaml
<Ribbon Name="ribbonMain">
<RibbonTab Header="Home">
<RibbonGroup Header="Employees" Width="200">
<ListBox x:Name="empListBox" ItemsSource="{Binding SelectedEmployees}"
Width="180"
MouseEnter="empListBox_MouseEnter"
MouseLeave="empListBox_MouseLeave">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Path=FirstName}" IsChecked="{Binding IsChecked}"></CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</RibbonGroup>
xaml.cs
private void empListBox_MouseEnter(object sender, MouseEventArgs e)
{
if (sender is ListBox)
{
ribbonMain.ReleaseMouseCapture();
((ListBox)sender).CaptureMouse();
}
}
private void empListBox_MouseLeave(object sender, MouseEventArgs e)
{
((ListBox)sender).ReleaseMouseCapture();
ribbonMain.CaptureMouse();
}
I think the problem is that the ListBox itself can't really do anything with the mouse capture. I think it's actually the scroll viewer inside the ListBox template that needs to receive the wheel events.
Try changing your mouse handlers like so:
private void empListBox_MouseEnter(object sender, MouseEventArgs e)
{
Mouse.Capture(empListBox, CaptureMode.SubTree);
}
private void empListBox_MouseLeave(object sender, MouseEventArgs e)
{
empListBox.ReleaseMouseCapture();
}
This will make mouse events visible to the element holding the capture *and* its descendant elements, including the scroll viewer.
Related
I have an WPF User control which is is hosted in an Elementhost. I use elementhost to include an WPF user control in my classical Windows forms app.
Now, from Windows forms side I am trying to capture the mouseDown event that is produced in an WPF label but I don't know how to do it.
Any ideas?
A case might be able to help you. The winform form calls the wpf control.
Create a WPF custom control. The xaml code of the control is as follows.
<Grid>
<Image Margin="10,10,10,90" x:Name="img" Stretch="Uniform" Opacity="1">
<Image.BitmapEffect>
<DropShadowBitmapEffect Opacity="1" />
</Image.BitmapEffect>
</Image>
<TextBox Background="Transparent" Foreground="White" Height="40" FontSize="32" Margin="44,0,56,36" x:Name="txtBox1" Opacity="0.5" Text="" VerticalAlignment="Bottom" /> </Grid>
You need to add the corresponding function to set the effect. The code is as follows.
public void SetSource(string fileName)
{
img.Source = new BitmapImage(new Uri(fileName) );
}
public void SetOpacity(double opacity)
{
img.Opacity = opacity;
}
//
public string GetText()
{
return txtBox1.Text;
}
Create a Winform application and add a reference, otherwise the control will not work properly. The list of references is pictured below.
Regenerate the solution. On the left toolbar, a WPF control appears and drag it to the form.
Use the button control in the winform project to call the corresponding function.
private void button1_Click(object sender, EventArgs e)
{
((UserControl1)elementHost1.Child).SetSource(#"C:\Users\Admin\Pictures\Saved Pictures\9837f99502eba3d01d4fb671cab20c15.jpg");
}
private void button2_Click(object sender, EventArgs e)
{
((UserControl1)elementHost1.Child).SetOpacity(0.5);
}
private void button3_Click(object sender, EventArgs e)
{
string text = ((UserControl1)elementHost1.Child).GetText();
label1.Text = text;
}
Test items: The left side is the traditional Winform control. The right side is the imported WPF control. You can clearly see the "translucent" effect of the picture.
Not sure what exactly you're trying to achieve. Below is a simple example.You can edit the MouseDown event of the UserControl as needed.
If there is a problem, please make your problem clearer and show me the complete code sample that can reproduce your problem for analysis.
UserControl:
<Grid>
<Label x:Name="label" Content="Label" MouseDown="label_MouseDown" Background="AliceBlue" Width="300" Height="200" />
</Grid>
private void label_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("hello");
}
Add the UserControl reference in the WinForms project, drag and drop the UserControl on the Form1 designer after rebuilding the WinForms project.
The result of running the project and clicking the Label in the UserControl is shown in the figure.
I have a DataGrid above an Expander and whenever I expand the Expander, a ScrollBar shows up in the DataGrid. However, when I collapse the Expander, the DataGrid's ScrollBar does not go away, even if there aren't enough Items in the DataGrid to warrant a ScrollBar.
I'm left with a empty ScrollBar.
Is there a way to update the DataGrid so that the ScrollBar logic can be re-executed?
<DataGrid x:Name="MyDataGrid"/>
<Expander Collapsed="Expander_OnCollapsed"/>
private void Expander_OnCollapsed(object sender, RoutedEventArgs e)
{
MyDataGrid.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
}
It's hard to tell exactly without any code to work with, but you could try:
<DataGrid x:Name="MyDataGrid">
<Expander Collapsed="Expander_OnCollapsed">
<!--Your fancy super awesome code here-->
</Expander>
</DataGrid>
Then in your code:
private void Expander_OnCollapsed(object sender, RoutedEventArgs e)
{
MyDataGrid.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
}
I have following ListView
<ListView Name="listAccounts" Width="300" AllowDrop="True" SelectionMode="Single" CanDragItems="True" CanDrag="True" CanReorderItems="True" Background="{ThemeResource myBackground}" DragItemsStarting="listAccounts_DragItemsStarting" Drop="listAccounts_Drop">
and defined my event handlers as
private void listAccounts_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
e.Data.SetData("itemIndex", (e.Items[0] as AccountList).Text.ToString());
}
private async void listAccounts_Drop(object sender, DragEventArgs e)
{
string itemIndexString = await e.Data.GetView().GetTextAsync("itemIndex");
}
I don't know what else I can do. I want to realize the movement of the list items in the same list.
I went over to the official Windows 10 samples, looked for the drag-drop sample and trimmed it down (like removing the drag from target to source). Turns out you don't even have to handle any events to make re-ordering in a single ListView work.
<ListView x:Name="TargetListView"
Grid.Row="2" Grid.Column="1" Margin="8,4"
CanReorderItems="True" CanDrag="True" AllowDrop="True"
/>
Check your ObservableCollection after reordering items and you'll notice it's correct. If you want to track the re-ordering, you'll have to check the CollectionChanged event on your ObservableCollection, as there is no event on the ListView to do this.
If you want to support drag & drop accross multilple listviews, I'd say have another look at the sample.
I have a Control that contains a Popup. I am trying to close the Popup whenever someone clicks outside of the Control. This is the part of my code that sets up the problem:
AddHandler(Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseuttonEventHandler(HandleOutsideClick), true);
Now whenever I click in the Popup it causes PreviewMouseDownOutsideCapturedElementEvent to be raised. Am I misunderstanding this event? Is there something that I can do to have the Popup be considered a part of the Control so that it doesn't raise this event?
Does this work?
<Popup Name="Pop" LostFocus="ClosePop"/>
private void ClosePop(object sender, RoutedEventArgs e)
{
Pop.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
}
Put the XAML code in your .xaml page and the C# code in the related .xaml.cs file.
Note: You may need to put the focus on the popup before this works, it may be done automatically; I haven't done this on popups, but I have done it on other objects.
Update: This works for me, clicking in the TextBox that says Test1 opens the Popup, and clicking in the TextBox labeled Test2 closes it:
<Grid Background="White">
<StackPanel>
<TextBox Foreground="Black" LostFocus="ClosePop" GotFocus="OpenPop" Height="50">Test1</TextBox>
<TextBox Foreground="Black" Height="50">Test2</TextBox>
</StackPanel>
<Popup Name="Pop" Height="50" Width="50">
<TextBlock Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center">Pop!</TextBlock>
</Popup>
</Grid>
private void ClosePop(object sender, RoutedEventArgs e)
{
Pop.IsOpen = false;
}
private void OpenPop(object sender, RoutedEventArgs e)
{
Pop.IsOpen = true;
}
When I tab into a ListBox control, the first item gets focused. When I have a label and set the target property to the ListBox (as shown in the code below) and then use the dedicated Alt shortcut then it will focus not the first item but the listbox itself (listbox border becomes dotted). What is the best way to avoid this unwanted behavior? Is there a way to disable focusing on the listbox itself and only allow focusing on the items?
Example code:
<Label Content="_Label" Margin="0,10,0,88" Name="MyLabel" Target="{Binding ElementName=MyListBox}" Height="Auto" />
<ListBox Width="100" Name="MyListBox" Margin="46,0,639,0" />
Behavior:
By setting Target you explicitly asked focus to move to listBox. In case you want to put it on first listBox item, you have to do it manually.
One way would be to hook GotFocus event and set focus to next available item using TravelRequest object which wil put it on first listBox item.
XAML:
<ListBox Width="100" Name="MyListBox" Margin="46,0,639,0"
GotFocus="MyListBox_GotFocus"/>
Code behind:
private void MyListBox_GotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource == sender)
{
TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next);
MyListBox.MoveFocus(request);
}
}