I am working with user controls.
I have a basic form that has 2 buttons btn_UC1, btn_UC2, and a panel
I have 2 user controls uc1, uc2 that have different tools to show various data
what I want to do:
On click of btn_UC1 I want to show uc1 in the panel
on click of btn_UC2 I want to show uc2 in the panel
But I don't want to close, clear, remove uc1 on click of btn_UC2, it should be in the background.
And same functionality on click of btn_UC1
Also when I close uc2, it should show uc1
I have tried using the clear functionality where the panel.cchildren.clear is called before showing any of the usercontrol.
C# WPF
UC1 Control1 = new UC1();
UC2 Control2 = new UC2();
private void btn_UC1_Click(object sender, RoutedEventArgs e)
{
try
{
//pnl_UC.Children.Remove(Control2);
pnl_UC.Children.Clear();
pnl_UC.Children.Add(Control1);
}
catch (Exception err)
{
}
}
private void btn_UC2_Click(object sender, RoutedEventArgs e)
{
try
{
pnl_UC.Children.Remove(Control1);
// pnl_UC.Children.Clear();
pnl_UC.Children.Add(Control2);
}
catch (Exception err)
{
}
}
<Window x:Class="UserControlTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:UserControlTest"
mc:Ignorable="d"
Title="MainWindow" Height="449.024" Width="870.182"
>
<Grid>
<Button x:Name="btn_UC1" Content="Button" HorizontalAlignment="Left" Margin="65,62,0,0" VerticalAlignment="Top" Width="159" Height="34" Click="btn_UC1_Click"/>
<Button x:Name="btn_UC2" Content="Button" HorizontalAlignment="Left" Margin="65,162,0,0" VerticalAlignment="Top" Width="159" Height="34" Click="btn_UC2_Click"/>
<StackPanel x:Name="pnl_UC" HorizontalAlignment="Left" Height="399" Margin="281,10,0,0" VerticalAlignment="Top" Width="573">
</StackPanel>
</Grid>
</Window>
You are removing Control1 from panel on click of btn_UC2. remove this from you code like below
private void btn_UC2_Click(object sender, RoutedEventArgs e)
{
try
{
pnl_UC.Children.Add(Control2);
}
catch (Exception err)
{
}
}
I suggest you to use an ItemsControl with a binding on an ObservableCollection, and from your codebehind you can Add / Remove things from this ObservableCollection. It's more mvvm.
Related
Sorry in advance if the title is confusing. Here's the situation. I have a grid called grdFilters. This grid has a series of CheckBoxes within it (one per row). Normally this grid is hidden. But I wanted it to show up when prompted (on button click) and leave when the user clicks somewhere other than the grid. To handle outside control mouse clicks I tried first capturing the mouse as such:
AddHandler(Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler(HandleClickOutsideOfControl));
private void HandleClickOutsideOfControl(object sender, MouseButtonEventArgs e)
{
if (this.filters) //Check if the Filters grid is visible
{
ShowHideMenu("sbHideFilters", grdFilters); //Method that hides the grid
Mouse.Capture(null); //Release the mouse
}
}
private void btnFilters_Click(object sender, RoutedEventArgs e)
{
if (!this.filters) //Check if the filters grid is shown
{
ShowHideMenu("sbShowFilters", grdFilters); //Method that reveals the grid
Mouse.Capture(grdFilters); //Capture the mouse
}
}
The problem is that while the Filters grid has captured the mouse, none of the grids children (the Check Boxes) can be clicked on. I would really like to find a way to detect when the mouse is clicked outside of the grid while still allowing the children of the grid to accept mouse down events. Any help would be greatly appreciated, thanks in advance.
As per request here is some of my Xaml:
<Grid>
<Label x:Name="label" Content="Events" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<ScrollViewer HorizontalAlignment="Left" Height="619" Margin="0,26,0,0" VerticalAlignment="Top" Width="450" VerticalScrollBarVisibility="Hidden">
<Grid x:Name="Schedule" HorizontalAlignment="Left" Height="Auto" VerticalAlignment="Top" Width="450" Margin="10,0,0,0"/>
</ScrollViewer>
<Grid x:Name="grdFilters" HorizontalAlignment="Left" Height="619" Margin="490,26,-176,0" VerticalAlignment="Top" Width="135" Background="{StaticResource TransparentBackground}" Panel.ZIndex="95">
<CheckBox x:Name="chckAll" Content="All" HorizontalAlignment="Left" Margin="0,10,0,0" VerticalAlignment="Top" Checked="chckAll_Checked" Unchecked="chckAll_Unchecked"/>
<Grid x:Name="grdFilters" HorizontalAlignment="Left" Height="588" Margin="0,31,0,0" VerticalAlignment="Top" Width="136"/>
</Grid>
<Button x:Name="btnFilters" Content="" Margin="436,223,-18,0" VerticalAlignment="Top" Background="Cyan" Opacity="0.15" Style="{StaticResource MyTabStyle}" Height="80" Click="btnFilters_Click"/>
</Grid>
The only thing I left out were the Resource Dictionaries and the page definition itself.
I think the Mouse.Capture and PreviewMouseDownOutsideCapturedElementEvent and are too specific for what you want.
I would rather use a hitResultsList, which can be used in a lot of different scenarios:
I slightly modified eh AddHandler
AddHandler(Mouse.PreviewMouseDownEvent, new MouseButtonEventHandler(HandleMouseDown));
And I added the VisualTreeHelper.HitTest logic
//List to store all the elements under the cursor
private List<DependencyObject> hitResultsList = new List<DependencyObject>();
private void HandleMouseDown(object sender, MouseButtonEventArgs e)
{
Point pt = e.GetPosition((UIElement)sender);
hitResultsList.Clear();
//Retrieving all the elements under the cursor
VisualTreeHelper.HitTest(this, null,
new HitTestResultCallback(MyHitTestResult),
new PointHitTestParameters(pt));
//Testing if the grdFilters is under the cursor
if (!hitResultsList.Contains(this.grdFilters) && grdFilters.Visibility == System.Windows.Visibility.Visible)
{
grdFilters.Visibility = System.Windows.Visibility.Hidden;
}
}
//Necessary callback function
private HitTestResultBehavior MyHitTestResult(HitTestResult result)
{
hitResultsList.Add(result.VisualHit);
return HitTestResultBehavior.Continue;
}
that way you can also remove the Mouse.Capture call from the btnFilters_Click:
private void btnFilters_Click(object sender, RoutedEventArgs e)
{
if (grdFilters.Visibility != System.Windows.Visibility.Visible)
grdFilters.Visibility = System.Windows.Visibility.Visible; }
}
I'm finding that when I tap the ScrollViewer, the PointerPressed and PointerExited events fires as expected. But, if I scroll in any direction after touching the screen and lift my finger, no event fires except for PointerCaptureLost which prematurely fires as soon as I scroll.
When I capture the pointer ID and poll the status of the PointerPoint with a timer, the IsInContact flag remains true, even after I lift my finger after scrolling. It works as expected when I simply tap the screen.
ManipulationCompleted has the same effect as above, and I cannot use the ViewChanged event since this fires before I lift my finger.
Is this a bug or am I missing something here? Is there another way I can detect when a user has lifted their finger off the screen? This is driving me bananas.
Sample code below. You'll need to use the simulator in touch-mode or have a touch capable screen to test:
Code:
using System;
using Windows.UI.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
namespace App1
{
public sealed partial class MainPage : Page
{
private readonly DispatcherTimer pointerTimer = new DispatcherTimer();
private uint? CurrentPointerID; //container for the current pointer id when user makes contact with the screeen
public MainPage()
{
this.InitializeComponent();
scrollviewer.PointerPressed += scrollviewer_PointerPressed;
scrollviewer.PointerMoved += scrollviewer_PointerMoved;
scrollviewer.PointerExited += scrollviewer_PointerExited;
scrollviewer.PointerReleased += scrollviewer_PointerReleased;
scrollviewer.PointerCaptureLost += scrollviewer_PointerCaptureLost;
scrollviewer.PointerCanceled += scrollviewer_PointerCanceled;
pointerTimer.Tick += pointerTimer_Tick;
pointerTimer.Interval = TimeSpan.FromMilliseconds(300);
pointerTimer.Start();
}
#region ScrollViewer Events
void scrollviewer_PointerMoved(object sender, PointerRoutedEventArgs e)
{
EventCalledTextBlock.Text = "Pointer Moved";
}
void scrollviewer_PointerExited(object sender, PointerRoutedEventArgs e)
{
EventCalledTextBlock.Text = "Pointer Exited";
}
void scrollviewer_PointerPressed(object sender, PointerRoutedEventArgs e)
{
CurrentPointerID = e.Pointer.PointerId;
EventCalledTextBlock.Text = "Pointer Pressed";
}
void scrollviewer_PointerCanceled(object sender, PointerRoutedEventArgs e)
{
EventCalledTextBlock.Text = "Pointer Canceled";
}
void scrollviewer_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
{
EventCalledTextBlock.Text = "Capture Lost";
}
void scrollviewer_PointerReleased(object sender, PointerRoutedEventArgs e)
{
EventCalledTextBlock.Text = "Pointer Released";
}
#endregion
void pointerTimer_Tick(object sender, object e)
{
if (!CurrentPointerID.HasValue)
{
PollingTextBlock.Text = string.Empty;
return;
}
try
{
var pointerPoint = PointerPoint.GetCurrentPoint(CurrentPointerID.Value);
PollingTextBlock.Text = pointerPoint.IsInContact ? "Is In Contact" : "Not in Contact";
}
catch (Exception ex)
{
//This exception is raised when the user lifts finger without dragging.
//assume finger is not in contact with screen
PollingTextBlock.Text = "Not in Contact";
}
}
}
}
XAML:
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Name="grid">
<Grid.RowDefinitions>
<RowDefinition Height="113*"/>
<RowDefinition Height="655*"/>
</Grid.RowDefinitions>
<ScrollViewer x:Name="scrollviewer" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Visible" Grid.Row="1" >
<Rectangle Fill="#FF3783CF" Height="100" Stroke="#FF33D851" Width="{Binding ElementName=grid, Path=ActualWidth}" Margin="100" StrokeThickness="4" />
</ScrollViewer>
<StackPanel Orientation="Vertical" Margin="45,25,0,0">
<StackPanel Orientation="Horizontal">
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Event Called:" VerticalAlignment="Top" FontSize="24" Margin="0,0,20,0"/>
<TextBlock x:Name="EventCalledTextBlock" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="24"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Polling Value:" VerticalAlignment="Top" FontSize="24" Margin="0,0,20,0"/>
<TextBlock x:Name="PollingTextBlock" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="24"/>
</StackPanel>
</StackPanel>
</Grid>
</Page>
I stumbled upon this question since I was struggling with a similar problem. I have a ScrollViewer which has several images in it and I wanted to know what images are shown at the moment the ScrollViewer stops moving...
In the end I did used the ScrollViewer.ViewChanged event. This event keeps triggering untill it has finished with scrolling.
I actually am only interested in the last of these events, but since there is no event that triggers only on that particular moment I need to respond to this one and check for myself if this is the appropriate moment to take actions.
I hope this helps.
ScrollViewer.ViewChanged event: https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.scrollviewer.viewchanged?f=255&MSPPError=-2147217396
I think you need to use the PointerReleased event.
Refer to the following link: https://msdn.microsoft.com/library/windows/apps/br208279
Afters attemps I could tell that the FocusVisualStyle is only activated by the keyboard (tab and arrows keys).
Try to make the FocusVisualStyle to be applied after the component is loaded, it is impossible to do, There is an easy way to get around this problem?
I found this:
- focus visual not showing when navigating focus programically
- How do WPF buttons decide to show FocusVisualStyle?
- http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/99856840-f8ef-4547-9150-c4c46ec2f3df
But none shows a definite solution (without overwriting the component), and I could not write, can someone help?
I am not pretty sure I understand your issue, but I tried the example in one of the links and I was able to move focus to next component from code behind exactly as you would do using keyboard. Here is the code.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:local="clr-namespace:WpfApplication1" Loaded="OnLoaded"
>
<StackPanel Margin="10">
<TextBox Margin="10" x:Name="a" >A</TextBox>
<TextBox Margin="10" x:Name="b" >B</TextBox>
<Button Focusable="False" Click="OnClick">Move Focus</Button>
</StackPanel>
</Window>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void OnLoaded(object sender, RoutedEventArgs e) {
a.Focus();
}
private void OnClick(object sender, RoutedEventArgs e) {
var request = new TraversalRequest(FocusNavigationDirection.Next);
var elementWithFocus = FocusManager.GetFocusedElement(FocusTest) as UIElement;
if (elementWithFocus != null)
elementWithFocus.MoveFocus(request);
}
}
I have this code:
private void ModifyButton_Click(object sender, RoutedEventArgs e)
{
ModifyButton.Content = "Another button name";
}
But it doesn't work. I mean, the modify button content doesn't change but the program doesn't fail or throw any exception.
I'm trying to modify the button name in order to change it's behavior (kinda Edit/Save) within the same button. Is this not possible using C#/WPF?
Thanks in advance.
EDIT:
XAML:
<Button Name="ModifyButton" Content="Modificar" Margin="5,10,0,0" Height="23" Width="120" HorizontalAlignment="Left" Click="ModifyButton_Click"></Button>
WEIRD BEHAVIOR: If I put a MessageBox.Show call after the change of the button content, then, while the message box is displayed the button dislay the new (changed) name, but after the message box is closed, then it shows it's original text.
I guess that the XAML of your UI is not bound to the value of your button. Did you check the DataBinding?
[EDIT]
Your magic information here is that you use ShowDialog(). As you already guessed, this influences your UI thread and therefore the display behavior. ShowDialog() displays the Form as a modal dialog and blocks your UI thread and therefore blocks the refresh of it. This may cause all sorts of weird behavior.
This is what i have and it works:
Window 1
<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>
<Button Name="ModifyButton" Content="Open Dialog" Margin="80,104,78,0" Height="23" Click="ModifyButton_Click" VerticalAlignment="Top"></Button>
</Grid>
</Window>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void ModifyButton_Click(object sender, RoutedEventArgs e)
{
Window2 win2 = new Window2();
win2.ShowDialog();
}
}
Window 2
<Window x:Class="WpfApplication1.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="300" Width="300">
<Grid>
<Button Name="ModifyButton" Content="Modificar" Margin="80,104,78,0" Height="23" Click="ModifyButton_Click" VerticalAlignment="Top"></Button>
</Grid>
</Window>
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
private void ModifyButton_Click(object sender, RoutedEventArgs e)
{
ModifyButton.Content = "Another button name";
}
}
I have two xaml files MainWindow.xaml and other user control WorkDetail.xaml file.
MainWindow.xaml file has a textbox, button, listbox and reference to WorkDetail.xaml(user control which is collapsed). Whenever user enter any text, it gets added in listbox when the add button is clicked. When any items from the listbox is double clicked, the visibility of WorkDetail.xaml is set to Visible and it gets displayed. In WorkDetail.xaml (user control) it has textblock and button. The Textblock displays the text of selected item and close button sets the visibility of WorkDetail window to collapsed. Now i am trying to animate WorkDetail.xaml when it gets visible and collapse. When any items from listbox is double clicked and WorkDetail.xaml visibility is set to visible, i want to create an animation of moving WorkDetail.xaml window from right to left on MainWindow. When Close button from WorkDetail.xaml file is clicked and WorkDetail.xaml file is collapsed, i want to slide the WorkDetail.xaml file from left to right from MainWindow.
Here is the screenshot:
MainWindow.xaml code:
<Window...>
<Grid Background="Black" >
<TextBox x:Name="enteredWork" Height="39" Margin="44,48,49,0" TextWrapping="Wrap" VerticalAlignment="Top"/>
<ListBox x:Name="workListBox" Margin="26,155,38,45" FontSize="29.333" MouseDoubleClick="workListBox_MouseDoubleClick"/>
<Button x:Name="addWork" Content="Add" Height="34" Margin="71,103,120,0" VerticalAlignment="Top" Click="Button_Click"/>
<TestWpf:WorkDetail x:Name="WorkDetail" Visibility="Collapsed"/>
</Grid>
</Window>
MainWindow.xaml.cs class code:
namespace TestWpf
{
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
workListBox.Items.Add(enteredWork.Text);
}
private void workListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
WorkDetail.workTextBlk.Text = (string)workListBox.SelectedItem;
WorkDetail.Visibility = Visibility.Visible;
}
}
}
WorkDetail.xaml code:
<UserControl ..>
<Grid Background="#FFD2CFCF">
<TextBlock x:Name="workTextBlk" Height="154" Margin="33,50,49,0" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="29.333" Background="#FFF13939"/>
<Button x:Name="btnClose" Content="Close" Height="62" Margin="70,0,94,87" VerticalAlignment="Bottom" Click="btnClose_Click"/>
</Grid>
</UserControl>
WorkDetail.xaml.cs class code:
namespace TestWpf
{
public partial class WorkDetail : UserControl
{
public WorkDetail()
{
this.InitializeComponent();
}
private void btnClose_Click(object sender, System.Windows.RoutedEventArgs e)
{
Visibility = Visibility.Collapsed;
}
}
}
Can anyone tell how can i do this?
is this link interesting for you? I think that something very similar is accomplished using a VisualBrush based technique. It's worth a look!
JAPF http://www.remote-screenshots.com/thumbs/medium/0/www.japf.fr.jpg
Another idea would be using the VisualStateManager and Transistions: You can overwrite the style information of your controls and use Storyboard animations - without tools like Blend this could become very tricky, though.
Hope that helps anyway.
best regards,
thomas