Letting users customize content property of user control at run-time - c#

This is the required behaviour:
I have various controls present on the canvas e.g. Callouts (from Expression Blend .dll), or simple Labels. When the user 'double clicks' (or any other event I decide to tie in) the control should change its appearance to allow the user to edit the control's Content property. Clicking off the control should then turn it back to 'read-only' method.
Any suggestions on how this would be best achieved? Ideally I want to do this all in c# to add this behaviour to the control at runtime (as this control is added dynamically to the canvas)- and avoid XAML altogether.
I reckon I've got to do something with adorners to display a textbox bound to the control's content property on the required event, but some code samples or links elsewhere would be appreciated? :) - I haven't been able to find anything on an existing search, but I reckon it should be fairly simple.

Unfortunately, style triggers do not do anything with IsReadOnly and IsEnabled. You would have to do that from an event.
Here is my sample:
WPF:
<Window x:Class="StateChangingTextbox.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">
<Window.Resources>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#eee" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox Width="300" Height="200" TextWrapping="Wrap" IsReadOnly="True"
MouseEnter="TextBox_MouseEnter"
MouseLeave="TextBox_MouseLeave"/>
</Grid>
</Window>
Code-behind:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void TextBox_MouseEnter(object sender, MouseEventArgs e)
{
var textbox = sender as TextBox;
if (textbox != null)
{
textbox.IsReadOnly = false;
}
}
private void TextBox_MouseLeave(object sender, MouseEventArgs e)
{
var textbox = sender as TextBox;
if (textbox != null)
{
textbox.IsReadOnly = true;
}
}
}

XAML:
<UserControl
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:ed="http://schemas.microsoft.com/expression/2010/drawing"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
mc:Ignorable="d"
x:Class="ComicWPF.Bubble"
x:Name="UserControl" Height="100" Width="200">
<Canvas LostFocus="this_LostFocus">
<ed:Callout x:Name="callout" Content=""
AnchorPoint="0,1" FontSize="14" Height="100" Width="200"
Fill="Blue"
PreviewMouseDoubleClick="Callout_DoubleClick"
Canvas.Left="0" Canvas.Top="0" />
<TextBox x:Name="textbox"
FontSize="14"
Canvas.Left="30" Height="55" Width="80" Canvas.Top="30"
Visibility="Visible"/>
</Canvas>
</UserControl>
C# Code:
private void Callout_DoubleClick(object sender, MouseButtonEventArgs e)
{
Activate();
}
public void Activate()
{
//set bool activated to true
//make textbox visible and set focus and select all text
}
private void Callout_DeSelect()
{
//set content of callout to the textbox.Text
//Hide textbox
//set bool activated to false
}
private void this_LostFocus(object sender, RoutedEventArgs e)
{
Callout_DeSelect();
}
}

Related

How to close current user Control and open new User control in WPF inside user control

I am new in WPF application i have to develop app with user control, User control will work like pages
I have open user control in MainWindow which will select language upon click and then close (current) language selection control and open another
MainWindow Code
<Window x:Class="WorkForceVisitor.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:WorkForceVisitor"
mc:Ignorable="d"
Title="Work Force Pro Visitor" Icon="Images/favicon.ico" Height="800" Width="1200">
<Window.Background>
<ImageBrush ImageSource="Images/bg.png"/>
</Window.Background>
<Grid Margin="10,0,1,5" RenderTransformOrigin="0.556,0.496" Height="754" VerticalAlignment="Bottom">
<StackPanel Name="myStack" Grid.Row="1" >
</StackPanel>
</Grid>
</Window>
MainWindow.cs
private Header _Header;
private Visitor _Visitor;
private Control _currentUser;
public MainWindow()
{
InitializeComponent();
_Header = new Header();
_LanguageSelection = new LanguageSelection();
_Visitor = new Visitor();
_currentUser = _LanguageSelection;
myStack.Children.Add(_currentUser);
}
user will click either arabic or english
upon button click we will close LanguageSelection control
and open Visitor controll in StackPanel Name="myStack"
which is inside the mainWindow
LanguageSelection
<UserControl x:Class="WorkForceVisitor.LanguageSelection"
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:WorkForceVisitor"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Margin="10,0,1,5" RenderTransformOrigin="0.556,0.496" Height="754" VerticalAlignment="Bottom">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0*"/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image MouseDown="EnglishPress" Grid.Column="1" HorizontalAlignment="Right" Height="200" Margin="0,0,38,272" VerticalAlignment="Bottom" Width="290" Source="Images/english.PNG">
<Image.OpacityMask>
<ImageBrush ImageSource="Images/arabic.PNG"/>
</Image.OpacityMask>
</Image>
<Image MouseDown="AranbicPress" Grid.Column="2" Height="200" Margin="50,0,0,272" VerticalAlignment="Bottom" Source="Images/arabic.PNG" RenderTransformOrigin="0.511,0.527" HorizontalAlignment="Left" Width="285">
<Image.OpacityMask>
<ImageBrush ImageSource="Images/english.PNG"/>
</Image.OpacityMask>
</Image>
<Image Grid.Column="1" HorizontalAlignment="Right" Height="100" Margin="0,0,440,517" VerticalAlignment="Bottom" Width="294" Grid.ColumnSpan="2" Source="Images/Logo.png"/>
</Grid>
</UserControl>
languageselection.cs
static bool isEnglish = false;
private void AranbicPress(object sender, MouseButtonEventArgs e)
{
// need to close current control and show visitor control in mainWindow
}
private void EnglishPress(object sender, MouseButtonEventArgs e)
{
// need to close current control and show visitor control in mainWindow
isEnglish = true;
}
I am not a pro, but this should work:
MainWindow.cs
public static Window Current;
private Header _Header;
private Visitor _Visitor;
private Control _currentUser;
public MainWindow()
{
Current = this;
InitializeComponent();
_Header = new Header();
_LanguageSelection = new LanguageSelection();
_Visitor = new Visitor();
_currentUser = _LanguageSelection;
myStack.Children.Add(_currentUser);
}
languageselection.cs
static bool isEnglish = false;
private void AranbicPress(object sender, MouseButtonEventArgs e)
{
MainWindow.Current.myStack.Children.Clear();
MainWindow.Current.myStack.Children.Add(MainWindow.Current._Visitor);
}
private void EnglishPress(object sender, MouseButtonEventArgs e)
{
MainWindow.Current.myStack.Children.Clear();
MainWindow.Current.myStack.Children.Add(MainWindow.Current._Visitor);
isEnglish = true;
}
However:
1) I don't think you need stackpanel inside of the grid for just one child;
2) I don't think you need to initialize your usercontrols before user needs them;
3) I would probably better create methods in the MainWindow to replace the controls.

Correct way of updating Property so that loading doesn't stop UI?

Sorry about the headline but it was the best I could come up with. Let me explain my problem: I have a WPF application that has a Menu looking much like your standard top menu that only takes up 5% of the screen. Click a menu item and the view below changes. The menu control is home-brewed because of reasons: Dynamic changes to menu-items, weird UI that doesn't fit existing controls, etc.
The menu changing view part is done using a ContentControl that binds to a "CurrentMenuView" property. When a menu item is clicked, this happens (pseudo-code):
private async void Button_Pressed(...)
{
await MakeSomeVisualMenuChanges();
CurrentMenuView = new CarsView();
await MakeSomOtherStuff();
}
The problem is that some views take some time to load, which makes the other steps happen slow also. I'd like to start loading the "CarsView" but at the same time (not after) continue with the other changes. So the user can see stuff happening.
I can solve this by using Task.Run() but that seems wrong as it puts stuff in a different context.
What is the correct / better way of dealing with this?
EDIT:
Thanks for all answers, as I expected this is not easy to explain. Let me try with a simple example:
MainWindows.xaml:
<Window x:Class="WpfApp32.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"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="300" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Button Grid.Row="0" Width="50" Content="Click" Click="Button_Click" />
<ContentControl Grid.Row="1" Width="200" Height="200" Content="{Binding PageContent, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
<TextBlock Grid.Row="2" Text="Bottom" Width="300" x:Name="BottomText" />
</Grid>
</Window>
Code-Behind:
using System.Windows;
using System.ComponentModel;
namespace WpfApp32
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
BottomText.Text = "AndNowforSomethingCompletelyDifferent";
PageContent = new UserControl1();
}
private object pageContent;
public object PageContent
{
get => pageContent;
set
{
pageContent = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PageContent)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
UserControl1.xaml:
<UserControl x:Class="WpfApp32.UserControl1"
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"
mc:Ignorable="d"
Loaded="UserControl_Loaded"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBlock x:Name="CtrlTextBlock" Width="100"/>
</Grid>
</UserControl>
UserControl1.cs:
using System.Windows;
using System.Windows.Controls;
namespace WpfApp32
{
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void Init()
{
System.Threading.Thread.Sleep(2000);
CtrlTextBlock.Text = "Loaded";
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
Init();
}
}
}
So this is stripped from async etc and just showing the issue. When the button is pressed, the UserControl1 is loaded but it takes 2 seconds to load. Until then, the text in the "BottomText" element remains unset.
As I said before, I can solve this by doing something like this in the button click:
private void Button_Click(object sender, RoutedEventArgs e)
{
BottomText.Text = "AndNowforSomethingCompletelyDifferent";
System.Threading.Tasks.Task.Run(() => Application.Current.Dispatcher.Invoke(() => PageContent = new UserControl1()));
}
But not sure that is the way to go. So the basic issue here, is that a ContentControl is bound to a property and setting that property might take some time. While that is loading I don't want execution in the MainWindow to be halted (I want the BottomText element to display "AndNowforSomethingCompletelyDifferent" immediately).
Here's an example that simulates 3 seconds of loading... It's not an extremely complex UI and binding to complex DataTemplates, especially nested, can slow things a bit but normally the drag comes from pulling the data.
The trick is having a clever UI that keeps things moving but also lets the user know it's waiting on something else to continue. The infamous loading bar for example... Not that I would use that exact process but that's the right idea.
Note and disclaimer: I almost despise code behind unless it's in a custom control of some type; never in the view. I always prefer MVVM and using a ViewModel for binding; but not to build or control the UI only for the data the UI uses. All that said because this example is none of that. I simply made the controls on the view and put the code behind for answering this question, with example, as simple as possible.
The View
<Window x:Class="Question_Answer_WPF_App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="500"
Width="800">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition />
</Grid.RowDefinitions>
<ToggleButton x:Name="menuButton"
Content="Menu"
Click="MenuButton_Click" />
<!--I do not recommend binding in the view like this... Make a custom control that does this properly.-->
<Grid x:Name="menu"
Visibility="{Binding IsChecked, Converter={StaticResource BooleanToVisibilityConverter}, ElementName=menuButton}"
VerticalAlignment="Top"
Grid.Row="1"
Background="Wheat">
<StackPanel x:Name="menuItems">
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
<TextBlock Text="simulated...." />
</StackPanel>
<StackPanel Name="menuLoading">
<TextBlock Text="Loading..."
FontSize="21" />
<ProgressBar IsIndeterminate="True"
Height="3" />
</StackPanel>
</Grid>
</Grid>
</Window>
Code Behind the View
using System.Threading.Tasks;
using System.Windows;
namespace Question_Answer_WPF_App
{
public partial class MainWindow : Window
{
public MainWindow() => InitializeComponent();
private Task SimulateLoadingResourcesAsnyc() => Task.Delay(3000);
private async void MenuButton_Click(object sender, RoutedEventArgs e)
{
menuItems.Visibility = Visibility.Collapsed;
menuLoading.Visibility = Visibility.Visible;
await SimulateLoadingResourcesAsnyc();
menuItems.Visibility = Visibility.Visible;
menuLoading.Visibility = Visibility.Collapsed;
}
}
}

Wpf PasswordBox must show characters when I click CheckBox

xaml
<Window x:Class="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">
<StackPanel VerticalAlignment="Center" Width="300">
<PasswordBox x:Name="PasswordBox1" Height="30" PasswordChar="*" Password="12345"/>
<CheckBox x:Name="CheckBox1" Content="Show Password"/>
</StackPanel>
</Window>
vb.net
Class MainWindow
Private Sub CheckBox1_Checked(sender As Object, e As RoutedEventArgs) Handles CheckBox1.Checked
PasswordBox1.PasswordChar = CChar("")
End Sub
Private Sub CheckBox1_Unchecked(sender As Object, e As RoutedEventArgs) Handles CheckBox1.Unchecked
PasswordBox1.PasswordChar = CChar("*")
End Sub
End Class
Run the above codes and click CheckBox1 in order to understand what is happening.
How can PasswordBox show characters which are 12345 when I click CheckBox?
So, following line need to be repaired.
PasswordBox1.PasswordChar = CChar(" ")
This will work for what you are looking for although it will expose your passwords in memory. We have a textbox and a password box in the same place on our UI and when the user checks the Show Password checkbox we collapse the passwordbox and show the hidden textbox, at the same time updating the text. You will need to check you are using the password from the visible ui control when you send the password.
Xaml code:
<StackPanel Orientation="Horizontal">
<Grid Width="300" Height="40">
<PasswordBox Name="passwordBox" PasswordChar="*" />
<TextBox Name="passwordTxtBox" Visibility="Collapsed" />
</Grid>
<CheckBox Margin="10" Name="showPassword" Unchecked="ShowPassword_Unchecked" Checked="ShowPassword_Checked" />
</StackPanel>
Code behind:
private void ShowPassword_Checked(object sender, RoutedEventArgs e)
{
passwordTxtBox.Text = passwordBox.Password;
passwordBox.Visibility = Visibility.Collapsed;
passwordTxtBox.Visibility = Visibility.Visible;
}
private void ShowPassword_Unchecked(object sender, RoutedEventArgs e)
{
passwordBox.Password = passwordTxtBox.Text;
passwordTxtBox.Visibility = Visibility.Collapsed;
passwordBox.Visibility = Visibility.Visible;
}
I recommend Using MahApps.Metro ... after installing it from nuget.org ... you must import it in the head of your xaml like this xmlns:controls="http://metro.mahapps.com/winf/xaml/controls"
and then ... just use it's style for your PasswordBox control
<PasswordBox Style="{StaticResource MetroButtonRevealedPasswordBox}" />
you can even change the content for the show icon using the controls:PasswordBoxHelper.RevealButtonContent attached property

Several problems with Popup (does not hide)

I made a small test-application to illustrate the behavior I do not understand: 2 buttons, if the mouse enters the left button a popup is shown (works), if the mouse enters the right button the popup should dissapear instantly (does not work). In my real application I have no buttons, only in this example for simple test, so the mouse movement is important and button-clicks cannot be used.
What I see is the following behavior:
If the popup is shown, the right button mouse-enter (hide) does not react at all, it seems that the popup has gotten focus, I have to click in the main window before the right mouse-enter becomes enabled. Setting Popup.Focusable=false (XAML) or trying to give focus to the grid (C# code) just after setting Popup.Isopen=true does not help.
Once I try to hide the popup by setting Popup.IsOpen=false, the popup stays visible and does not disappear. Only when I click the main window topbar, or when I hover the minimize button for example which shows a tooltip, the popup suddenly disappears. Calling UpdateLayout() on several UI elements does not help.
I'd like the following:
Once the popup is shown, the hide button should still react on mouse-enter.
Setting Popup.IsOpen=false should directly let the popup disappear.
See code below, XAML:
<Window x:Class="WpfApplication1.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:WpfApplication1"
mc:Ignorable="d"
x:Name="MyWindow"
Title="MainWindow" Height="500" Width="800">
<Grid>
<Grid x:Name="MyGrid" Margin="100" Background="Green">
<TextBox x:Name="MyText" Width="100" Height="50" Margin="0,50" HorizontalAlignment="Center"></TextBox>
<Button Width="75" Height="50" Margin="20,100" HorizontalAlignment="Left"
Content="Show" MouseEnter="MouseEnterShow"></Button>
<Button Width="75" Height="50" Margin="20,100" HorizontalAlignment="Right"
Content="Hide" MouseEnter="MouseEnterHide"></Button>
<Popup x:Name="MyPopup" PlacementTarget="{Binding ElementName=MyGrid}" Placement="RelativePoint"
AllowsTransparency="false" IsOpen="False" StaysOpen="False"
Focusable="False"
Width="200" Height="200"
HorizontalAlignment="Left" VerticalAlignment="Top"
HorizontalOffset="-50" VerticalOffset="-50">
<Grid>
<Canvas Background="BlanchedAlmond" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></Canvas>
</Grid>
</Popup>
</Grid>
</Grid>
</Window>
And C#:
using System.Windows;
using System.Windows.Input;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void MouseEnterShow(object sender, MouseEventArgs e)
{
MyPopup.IsOpen = true;
MyGrid.Focus();// Does not help
MyText.Text = "Show";
System.Diagnostics.Debug.WriteLine("Show");
}
private void MouseEnterHide(object sender, MouseEventArgs e)
{
MyPopup.IsOpen = false;
MyGrid.UpdateLayout();// Does not help
MyText.Text = "Hide";
System.Diagnostics.Debug.WriteLine("Hide");
}
}
}
After some brute forcing, I've managed to make it work:
1.Set the Popup property StaysOpen to true, instead of false
2.Code behind
private void MouseEnterShow(object sender, MouseEventArgs e)
{
MyPopup.IsOpen = true;
}
private void MouseEnterHide(object sender, MouseEventArgs e)
{
MyPopup.IsOpen = false;
}

How can I force an image to overlay on the title bar of my WPF application?

I have a WPF application that has an animated .gif used to briefly direct user attention. The .gif sits just outside of the bounds of my app's window, such that it is underneath, and covered by, the title bar.
See below:
Is there a way to force it to overlay on top? It's defined in XAML like this:
<Grid>
<Image Margin="-5 -45 0 0" DockPanel.Dock="Left" gif:ImageBehavior.AnimatedSource="/Resources/jump.gif"
Width="30" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="45"/>
<TranslateTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</Grid>
And it looks alright at design-time:
I tried using DockPanel instead of Grid as its container to no avail.
Lastly, is it possible to have it behave as though it was collapsed? That is, have it not take up horizontal space between the ComboBox and the Legend Label
You need to use a Popup so that it gets its own window handle. This will also make it not take up space in the layout. As an added bonus (or maybe headache) you will be able to position it with its PlacementTarget and PlacementMode properties, since it looks like that is what you are trying to do anyway.
I used a Popup and it is working quite well, but with some very little flickering.
<Window x:Name="Window1" .../>
<Grid>
<Button Content="Show" HorizontalAlignment="Left" Margin="160,114,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
<Button Content="Hide" HorizontalAlignment="Left" Margin="265,114,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_2"/>
<Popup x:Name="Popup1" UseLayoutRounding="True" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Window1}">
<Image Source="C:\\Users\\Public\\Pictures\\Sample Pictures\\desert.jpg" Stretch="Fill" Width="75" Height="25"/>
</Popup>
</Grid>
</Window>
Code :
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Popup1.IsOpen = true;
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
Popup1.IsOpen = false;
}
private void Window1_LocationChanged(object sender, EventArgs e)
{
double offset = Popup1.HorizontalOffset;
Popup1.HorizontalOffset = offset + 1;
Popup1.HorizontalOffset = offset;
}
Another approach (recommended) without Popup !
XAML
MainWindow.xaml
<Window x:Class="WpfWindow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="Window1" Title="MainWindow" Height="350" Width="525"
Closing="Window1_Closing" Activated="Window1_Activated" LocationChanged="Window1_LocationChanged">
<Grid x:Name="root"/>
</Window>
TitleBarWindow.xaml
<Window x:Class="WpfWindow.TitleBarWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Topmost="True"
Title="TitleBarWindow" AllowsTransparency="True" WindowStyle="None" Height="25" Width="200">
<Grid>
<Image Source="g:\\jellyfish.jpg" Stretch="Fill" HorizontalAlignment="Stretch"/>
</Grid>
</Window>
MainWindow.xaml.cs
namespace WpfWindow
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
TitleBarWindow w = new TitleBarWindow();
public MainWindow()
{
InitializeComponent();
w.ShowActivated = true;
w.Background = Brushes.Red;
}
private void Window1_LocationChanged(object sender, EventArgs e)
{
Point pt = Window1.PointToScreen(new Point(0, 0));
w.Top = pt.Y - 27;
w.Left = pt.X;
}
private void Window1_Activated(object sender, EventArgs e)
{
Point pt = Window1.PointToScreen(new Point(0, 0));
w.Top = pt.Y-27;
w.Left = pt.X;
w.Show();
}
private void Window1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
w.Close();
}
}
}
Second approach is very good, works smoothly.

Categories