How to programmatically set UserControl to Topmost? - wpf

How to programmatically set UserControl to Topmost of pc screen. I have multiple usercontrol in my wpf application, when I resize any usercontrol, I want to show this usercontrol top of the screen.

i want to show this usercontrol top of the screen.
If by that you mean "top of the screen" inside your application, then that is achieved by using Panel's ZIndex attached property.
Xaml :
<Grid x:Name="LayoutRoot">
<UserControl x:Name="TopMostUserControl"
Margin="10,140,106,48"
Panel.ZIndex="1"
Background="Green" />
<UserControl x:Name="SecondUserControl"
Margin="39,50,37,87"
Panel.ZIndex="0"
Background="red" />
</Grid>
C# :
public MainWindow()
{
InitializeComponent();
Panel.SetZIndex(TopMostUserControl, 1);
Panel.SetZIndex(SecondUserControl, 0);
}
<Grid x:Name="LayoutRoot">
<UserControl x:Name="TopMostUserControl"
Margin="10,140,106,48"
Background="Green" />
<UserControl x:Name="SecondUserControl"
Margin="39,50,37,87"
Background="red" />
</Grid>
Result :
However, if you mean to topmost that UserControl on the entire screen, then that would be something different, you should create another Window that hosts your topmost UserControl and you should change its TopMost property to true when you resize your other UserControls.
MainWindow :
<Grid x:Name="LayoutRoot">
<UserControl x:Name="FirstUserControl"
Margin="10,140,106,48"
Background="Green"
MouseDown="FirstUserControl_OnMouseDown" />
<UserControl x:Name="SecondUserControl"
Margin="39,50,37,87"
Background="red" />
</Grid>
Code Behind :
public partial class MainWindow : Window
{
public TopMostWindow TopMostWindow;
public MainWindow()
{
InitializeComponent();
TopMostWindow = new TopMostWindow();
TopMostWindow.Show();
}
private void FirstUserControl_OnSizeChanged(object sender, SizeChangedEventArgs e)
{
TopMostWindow.Topmost = true;
}
private void MainWindow_OnContentRendered(object sender, EventArgs e)
{
FirstUserControl.SizeChanged += FirstUserControl_OnSizeChanged;
SecondUserControl.SizeChanged += FirstUserControl_OnSizeChanged;
}
//This is to simulate the resizing
private void FirstUserControl_OnMouseDown(object sender, MouseButtonEventArgs e)
{
FirstUserControl.Width = 400;
}
}
TopMostWindow :
<Window x:Class="MvvmLight1.TopMostWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TopMostWindow"
Width="300"
Height="300"
Topmost="False"
WindowStyle="None">
<Grid>
<UserControl x:Name="TopMostUserControl" Background="Blue" />
</Grid>
</Window>

It depends in which container you are using it. Or in what scenario. Basically in Grid you just need to specify it as a last element under Grid container. Otherwise use Panel.ZIndex="1" on the UserControl declaration in XAML

Related

Modify WPF Window when Submenu opens without closing Submenu

I have a Window with a Menu on it. When the Menu is opened, I would like to change the Window's appearance to look disabled. Simply covering it with a gray Rectangle looks nice. Here is the Window markup:
<Grid>
<!--Content-->
<ContentControl Content="{Binding CurrentViewModel}" />
<!--Container to hide content-->
<Rectangle x:Name="Disabler" Fill="#77000000" Visibility="{Binding DisableWindow, Converter={StaticResource BoolToVisibilityConverter}}" />
</Grid>
I tried to set DisableWindow to true when the Submenu opens and false when it closes. However, setting this value seems to close the Submenu. How can I ensure the Submenu stays open?
private void MenuItem_SubmenuOpened(object sender, RoutedEventArgs e)
{
MainWindowViewModel mainVM = Window.GetWindow(this).DataContext as MainWindowViewModel;
if (mainVM != null)
{
mainVM.DisableWindow = true;
}
}
Edit: Since the Rectangle gets set to Visible, the MouseUp event is happening on Disabler. This is why the Submenu closes on me. I tried setting IsHitTestVisible="False" on the Rectangle, but that makes everything under it clickable. Is there a way to keep the Rectangle from stealing focus?
Instead of overlapping the grid with Rectangle, I divided my 2 half.
Is the Menu bar (10 % of screen)
Rectangle area (90% of screen)
Xaml of the screen
<Window x:Class="WpfApp4.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:WpfApp4"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d" x:Name="Window1"
Title="MainWindow" Height="450" Width="800">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="35"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border>
<Border.Effect>
<BlurEffect Radius="{Binding ElementName=Window1,Path=DataContext.Radius}" KernelType="Gaussian"/>
</Border.Effect>
<Menu Grid.Row="0" x:Name="Menubar" HorizontalAlignment="Left" Height="24" Margin="10,10,0,0" VerticalAlignment="Top" Width="772" >
<MenuItem Header="Home" SubmenuOpened="MenuItem_SubmenuOpened" SubmenuClosed="MenuItem_SubmenuClosed" >
<MenuItem Header="Office" >
<MenuItem Header="Ground Floor"/>
</MenuItem>
<MenuItem Header="Exit" />
</MenuItem>
</Menu>
</Border>
<Rectangle Grid.Row="1" x:Name="Disabler" Fill="{Binding ElementName=Window1, Path=DataContext.BackGroundColor}" />
</Grid>
As you can see in the Xaml, I have used 2 events SubmenuOpened and SubmenuClosed.
These 2 Methods are responsible to flip the rectangle fill Brush color.
In ViewModel/CodeBehind, I have created 1 property called BackGroundColor, which will be having white color when menu is not clicked and will have grey if we click on Menu.
BackGroundColor will be binded with the Rectangle's Fill property.
Code Behind
public partial class MainWindow : Window,INotifyPropertyChanged
{
private Brush _backGroundcolor;
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public int _radius { get; set; }
public int Radius
{
get
{
return _radius;
}
set
{
_radius = value;
NotifyPropertyChanged(nameof(Radius));
}
}
public Brush BackGroundColor
{
get
{
return _backGroundcolor;
}
set
{
_backGroundcolor = value;
NotifyPropertyChanged(nameof(BackGroundColor));
}
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void MenuItem_SubmenuOpened(object sender, RoutedEventArgs e)
{
BackGroundColor = new SolidColorBrush(Colors.Gray);
Radius = 5;
}
private void MenuItem_SubmenuClosed(object sender, RoutedEventArgs e)
{
BackGroundColor = new SolidColorBrush(Colors.White);
Radius = 0;
}
}
Check out the Menu clicked image below.
I had to go with setting IsHitTestVisible="False" on the Rectangle, even though that makes everything under it clickable. It's a hack, and I would love a better fix.

wpf how to change a canvas image Position programmatically

I am a student on my final year and im doing a project regarding WPF but i'm totally new to WPF and i have been assigned some tasks,but im currently stuck on how to change the Image position on the canvas programitically from left to right.below are the codes
<<Window x:Class="changing_bird_position.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<Canvas Name="canvas" Background="LightBlue" Width="500" Height="280" Margin="264,0,28,0">
<Image Source="inlandbird.png" Name="Image" Height="43" Canvas.Left="55" Canvas.Top="22"/>
</Canvas>
<Button Content="Button" Click="Button_Click" Width="50" Height="50" Margin="246,0"/>
</StackPanel>
Xaml.cs
public partial class MainWindow : Window
{
Image img = new Image();
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Canvas.SetLeft(img, 200.0);
Canvas.SetTop(img, 200.0);
In your code behind you don't need to create this instance of an Image (img). You can access the image by it's name property.
I renamed the image in the xaml to make it clear.
XAML:
<Window x:Class="WpfApplication15.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<Canvas Name="canvas" Background="LightBlue" Width="500" Height="280" Margin="264,0,28,0">
<Image Source="inlandbird.png" Name="BirdImage" Height="43" Canvas.Left="55" Canvas.Top="22"/>
</Canvas>
<Button Content="Button" Click="Button_Click" Width="50" Height="50" Margin="246,0"/>
</StackPanel>
</Window>
Code behind:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Canvas.SetLeft(BirdImage, 200.0);
Canvas.SetTop(BirdImage, 200.0);
}
}
}

Set focus to a usercontrol when it is made visible

I am showing a MessageBox and want the user to be able to copy the contents of the message using CTRL+C. The problem is that I can't seem to set focus to the dialog.
The MessageBox is implemented in MVVM. To show it I just make a usercontrol visible (centre screen) and disable the main view.
The copy command is implemented using a Prism DelegateCommand:
<UserControl.InputBindings>
<KeyBinding Key="C" Modifiers="Control" Command="{Binding CopyCommand}"/>
</UserControl.InputBindings>
If I tab onto on of the message box button the CopyCommand fires. However I cannot get it to work initially when the dialog is shown.
How do I get the usercontrol to accept focus or to attach the KeyBinding to the whole of the usercontrol?
Note: I need an MVVM solution as don't want any code in the code behind file.
In situations when using MVVM pattern and need to interact with the user interface, I always try to implement this solution through an attached behavior. Attached behavior is very powerful and convenient solution that fully satisfies the MVVM pattern, which can also be used in the Blend (with a pre-defined interface).
In this case, I created an attached behavior VisibleFocusBehavior, which set a IsVisibleChanged event handler, wherein the focus is set in the case of the visibility of the element.
To avoid the appearance of dotted box, when the control gets focus, I set FocusVisualStyle="{x:Null} for UserControl.
VisibleFocusBehavior
public class VisibleFocusBehavior
{
#region IsFocusEnabled Dependency Property
public static readonly DependencyProperty IsFocusEnabledProperty;
public static void SetIsFocusEnabled(DependencyObject DepObject, bool value)
{
DepObject.SetValue(IsFocusEnabledProperty, value);
}
public static bool GetIsFocusEnabled(DependencyObject DepObject)
{
return (bool)DepObject.GetValue(IsFocusEnabledProperty);
}
#endregion
#region BringToFrontBehavior Constructor
static VisibleFocusBehavior()
{
IsFocusEnabledProperty = DependencyProperty.RegisterAttached("IsFocusEnabled",
typeof(bool),
typeof(VisibleFocusBehavior),
new UIPropertyMetadata(false, IsFocusTurn));
}
#endregion
#region IsFocusTurn
private static void IsFocusTurn(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
UIElement element = sender as UIElement;
if (e.NewValue is bool && ((bool)e.NewValue) == true)
{
if (element != null)
{
element.IsVisibleChanged += new DependencyPropertyChangedEventHandler(ElementIsVisibleChanged);
}
}
}
#endregion
#region ElementIsVisibleChanged Handler
private static void ElementIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
UIElement visibilityElement = sender as UIElement;
if (visibilityElement.IsVisible == true)
{
visibilityElement.Focus();
}
}
#endregion
}
Example of using
<UserControl x:Class="UserControlFocusHelp.TestUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UserControlFocusHelp"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300"
xmlns:AttachedBehaviors="clr-namespace:UserControlFocusHelp.AttachedBehaviors"
AttachedBehaviors:VisibleFocusBehavior.IsFocusEnabled="True"
FocusVisualStyle="{x:Null}">
<UserControl.InputBindings>
<KeyBinding Key="C"
Modifiers="Control"
Command="{Binding CopyCommand}" />
</UserControl.InputBindings>
Test window
XAML
<Grid>
<local:TestUserControl x:Name="TestUserControl"
Width="300"
Height="300"
Focusable="True"
Visibility="Collapsed" />
<Button Width="100"
Height="30"
Content="Visible"
HorizontalAlignment="Left"
Click="Button_Click" />
</Grid>
Code-behind
private void Button_Click(object sender, RoutedEventArgs e)
{
TestUserControl.Visibility = Visibility.Visible;
}
Full example is available at this link.
There is a simple way to set focus to a control. Here's an example:
<UserControl
FocusManager.FocusedElement="{Binding ElementName=txtNickname}">
<Grid>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox x:Name="txtNickname" Grid.Row="1" />
</Grid>
</Grid>

WPF ScrollViewer/Canvas mouse event handler

I've created the following control:
<UserControl x:Class="FooBar.AnnotationControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="400" Width="500" >
<ScrollViewer Height="400" Width="500">
<Canvas Height="400" Width="500" Name="ctlCanvas" MouseLeftButtonDown="MouseLeftButtonDownHandler" >
<Canvas.RenderTransform>
<ScaleTransform x:Name="ZoomTransform" />
</Canvas.RenderTransform>
</Canvas>
</ScrollViewer>
</UserControl>
namespace FooBar
{
public partial class AnnotationControl : UserControl
{
public AnnotationControl()
{
InitializeComponent();
}
private void MouseLeftButtonDownHandler( object sender, MouseButtonEventArgs args)
{
//Do Something
}
}
}
when I click the canvas, I don't hit breakpoints in the MouseLeftButtonDownHandler. I even attach this handler to the ScrollViewer and get the same result. Any idea what's going on here?
The default background for a Canvas is Transparent, which allows hit tests to pass through it. To make your Canvas register for HitTests, give it a Background Color.
<Canvas Background="White" ... />

How to create controls from code in a custom control?

In MainPage.xaml.cs (Silverlight Application) I can do something like this:
StackPanel myStackPanel = new StackPanel();
Button myButton = new Button();
myButton.Content = "Button";
myButton.Width = 200;
myButton.Height = 30;
Button myButton1 = new Button();
myButton1.Content = "Button 1";
myButton1.Width = 200;
myButton1.Height = 30;
myStackPanel.Children.Add(myButton);
myStackPanel.Children.Add(myButton1);
this.LayoutRoot.Children.Add(myStackPanel);
What is the equivalent of this code in a custom control when I'm trying to create these controls from the code?
Update:
My question is probably too confusing. I'l try better formulation.
So, I have
Generic.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DemoAddControlLib">
<Style TargetType="local:DemoControlShowtime">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:DemoControlShowtime">
<Grid x:Name="LayoutRootControl">
<Button x:Name="Button1" Content="Hi" Width="150" Height="30"></Button>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
And code:
DemoControlShowtime.cs
[TemplatePart(Name = "Button1", Type=typeof(Button))]
public class DemoControlShowtime : Control
{
public DemoControlShowtime()
{
this.DefaultStyleKey = typeof(DemoControlShowtime);
}
// Events
public override void OnApplyTemplate()
{
Button1 = (Button)GetTemplateChild("Button1");
}
private Button button1;
private Button Button1
{
get { return button1; }
set
{
if (button1 != null)
{
Button1.Click -= new RoutedEventHandler(myButton_Click);
}
button1 = value;
button1.Click += new RoutedEventHandler(myButton_Click);
}
}
void myButton_Click(object sender, RoutedEventArgs e)
{
Button1.Content = "Hello Button";
}
}
If I click on Button1 the Content changes from "Hi" to "Hello Button". I want, when Button1 is clicked, to add StackPanel with two buttons as its Children into the Grid LayoutRootControl.
I know there is Visibility property and put it into the xaml would be easier but I'm curious how to do it from the code.
I hope this is much clearer than the question was before.
The code isn't really any different to what you have. The only variation is that the field LayoutRoot is not created for you.
However with this line of code:-
Grid LayoutRoot = GetTemplateChild("LayoutRootControl") as Grid;
The rest of your code would be identical (although you should test whether LayoutRoot is null first).
It appears to me that your are just wondering how to use a custom control in multiple places.
I've created a custom control (MyCustomControl) that has the StackPanel shown in your code, then used it multiple times on the MainPage.
MyCustomControl.xaml
<UserControl x:Class="SilverlightApplication2.MyCustomControl"
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"
mc:Ignorable="d">
<StackPanel>
<Button Content="Button 1" Height="30" Width="200"/>
<Button Content="Button 2" Height="30" Width="200"/>
</StackPanel>
MyCustomControl.xaml.cs
public partial class MyCustomControl : UserControl
{
public MyCustomControl()
{
InitializeComponent();
}
}
Then I've used that custom control twice in the main view.
MainPage.xaml
<UserControl x:Class="SilverlightApplication2.MainPage"
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"
mc:Ignorable="d"
xmlns:local="clr-namespace:SilverlightApplication2"
d:DesignHeight="300" d:DesignWidth="400">
<StackPanel>
<local:MyCustomControl Margin="10" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<local:MyCustomControl Margin="10" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
MainPage.xaml.cs
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
}
Output

Resources