WPF / C# - Dialog Window doesn't respond to Touch - c#

I'm developing a C# WPF application that is intended to run on full Windows 10 tablets using exclusively touch. So far, the app works great, except for one of my dialog windows has buttons that don't like to be touched.
Dialog Window XAML:
<Window x:Class="Commencement_Organizer.ConfirmStudentWindow"
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:Commencement_Organizer"
mc:Ignorable="d"
Title="Confirmation" Topmost="True" Height="372.677" Width="578.225" ResizeMode="NoResize" WindowStartupLocation="CenterScreen"
WindowStyle="None" Background="White" AllowsTransparency="True" Stylus.IsTapFeedbackEnabled="False" Stylus.IsTouchFeedbackEnabled="False">
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="00:00:0.2" Storyboard.TargetProperty="Opacity" From="0" To="1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Grid Background="#FF171717">
<Grid Margin="1" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button x:Name="YesButton" Content="Yes" Margin="25" Grid.Row="2" Click="YesButton_Click"/>
<Button x:Name="NoButton" Content="No" Margin="25" Grid.Row="2" Grid.Column="1" Click="NoButton_Click"/>
<Label x:Name="label" Content="Confirm your name" Margin="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="24"/>
<Label x:Name="nameLabel" Content="Label" HorizontalAlignment="Center" Margin="0" Grid.Row="1" VerticalAlignment="Center" Grid.ColumnSpan="2" FontSize="24" FontWeight="Bold"/>
</Grid>
</Grid>
Implementation (C#):
ConfirmStudentWindow confirmWindow = new ConfirmStudentWindow(student);
confirmWindow.Confirm += OnConfirm;
// This window makes everything behind the dialog window a grey tint, which makes the dialog more prominent
var darkwindow = new Window()
{
Background = Brushes.Black,
Opacity = 0.4,
AllowsTransparency = true,
WindowStyle = WindowStyle.None,
WindowState = WindowState.Maximized,
Topmost = true,
Effect = new BlurEffect()
};
darkwindow.Show(); // Show grey background tint
confirmWindow.ShowDialog(); // Stops main UI thread
darkwindow.Close();
Everything about this works as intended, except when I try to use a touchscreen to use those buttons, they just stay highlighted, but don't actually click. Works perfect with a mouse.
Tested on 2 different Windows 10 Devices (Surface Pro 2 and Surface Book).
To put it in the form of a question:
Why does launching this window as a Dialog make it resistant to touch, but not if it's launched as a regular window?
Edit - New Question:
Is there any way to simulate a Dialog window other than launching a regular window that always stays on top and then put a tinted overlay behind it while giving the window an eventhandler that provides the result of the user input?

I tried your example and it is running without any problem at my end. I am using DELL notebook with touch display with W10 and .NET 4.5.2. One thing that I can suggest you is to try to hook up StylusUp (or StylusDown that depends on your logic) event on buttons in dialog. I did encounter similar problems in the past when only click event was managed.
This worked for me, confirm method was called and dialog closed.
ConfirmStudentWindow.xaml.cs
using System;
using System.Windows;
using System.Windows.Input;
namespace DialogTouchTest
{
/// <summary>
/// Interaction logic for ConfirmStudentWindow.xaml
/// </summary>
public partial class ConfirmStudentWindow : Window
{
public Action Confirm;
public ConfirmStudentWindow()
{
InitializeComponent();
}
private void YesButton_Click(object sender, RoutedEventArgs e)
{
e.Handled = true;
Yes();
}
private void NoButton_Click(object sender, RoutedEventArgs e)
{
e.Handled = true;
No();
}
private void YesButton_StylusUp(object sender, StylusEventArgs e)
{
e.Handled = true;
Yes();
}
private void NoButton_StylusUp(object sender, StylusEventArgs e)
{
e.Handled = true;
No();
}
private void Yes()
{
DialogResult = true;
Confirm();
}
private void No()
{
DialogResult = false;
}
}
}
ConfirmStudentWindow.xaml
<Window x:Class="DialogTouchTest.ConfirmStudentWindow"
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="Confirmation" Topmost="True" Height="372.677" Width="578.225" ResizeMode="NoResize" WindowStartupLocation="CenterScreen"
WindowStyle="None" Background="White" AllowsTransparency="True" Stylus.IsTapFeedbackEnabled="False" Stylus.IsTouchFeedbackEnabled="False">
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="00:00:0.2" Storyboard.TargetProperty="Opacity" From="0" To="1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Grid Background="#FF171717">
<Grid Margin="1" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button x:Name="YesButton" Content="Yes" Margin="25" Grid.Row="2" StylusUp="YesButton_StylusUp" Click="YesButton_Click"/>
<Button x:Name="NoButton" Content="No" Margin="25" Grid.Row="2" Grid.Column="1" StylusUp="NoButton_StylusUp" Click="NoButton_Click"/>
<Label x:Name="label" Content="Confirm your name" Margin="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="24"/>
<Label x:Name="nameLabel" Content="Label" HorizontalAlignment="Center" Margin="0" Grid.Row="1" VerticalAlignment="Center" Grid.ColumnSpan="2" FontSize="24" FontWeight="Bold"/>
</Grid>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Effects;
namespace DialogTouchTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
ConfirmStudentWindow confirmWindow = new ConfirmStudentWindow();
confirmWindow.Confirm += OnConfirm;
// This window makes everything behind the dialog window a grey tint, which makes the dialog more prominent
var darkwindow = new Window()
{
Background = Brushes.Black,
Opacity = 0.4,
AllowsTransparency = true,
WindowStyle = WindowStyle.None,
WindowState = WindowState.Maximized,
Topmost = true,
Effect = new BlurEffect()
};
darkwindow.Show(); // Show grey background tint
confirmWindow.ShowDialog(); // Stops main UI thread
darkwindow.Close();
}
private void OnConfirm()
{
}
}
}

Comparing two identical .Show() methods, one being executed from a ViewModel and the other executed in code-behind, I found that the code-behind instance did not detect touches.
My solution was to invoke the method on the main UI thread from code-behind:
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
{
window.Show()
}));
Beware that if you expect a result from the dialog then you will need to include it within the `Dispatched.BeginInvoke' method, otherwise it will not work correctly.
Ideally, grouping all relevant logics within would be the best approach.

Related

Missing References in References Manages "No items found" - WPF [duplicate]

Is there a standard message box in WPF, like WinForms' System.Windows.Forms.MessageBox.Show(), or should I use the WinForms message box?
The WPF equivalent would be the System.Windows.MessageBox. It has a quite similar interface, but uses other enumerations for parameters and return value.
You can use this:
MessageBoxResult result = MessageBox.Show("Do you want to close this window?",
"Confirmation",
MessageBoxButton.YesNo,
MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
Application.Current.Shutdown();
}
For more information, visit MessageBox in WPF.
WPF contains the following MessageBox:
if (MessageBox.Show("Do you want to Save?", "Confirm",
MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
{
}
The equivalent to WinForms' MessageBox in WPF is called System.Windows.MessageBox.
In WPF it seems this code,
System.Windows.Forms.MessageBox.Show("Test");
is replaced with:
System.Windows.MessageBox.Show("Test");
The MessageBox in the Extended WPF Toolkit is very nice. It's at Microsoft.Windows.Controls.MessageBox after referencing the toolkit DLL. Of course this was released Aug 9 2011 so it would not have been an option for you originally. It can be found at Github for everyone out there looking around.
If you want to have your own nice looking wpf MessageBox:
Create new Wpf Windows
here is xaml :
<Window x:Class="popup.MessageboxNew"
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:popup"
mc:Ignorable="d"
Title="" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterScreen" WindowStyle="None" ResizeMode="NoResize" AllowsTransparency="True" Background="Transparent" Opacity="1"
>
<Window.Resources>
</Window.Resources>
<Border x:Name="MainBorder" Margin="10" CornerRadius="8" BorderThickness="0" BorderBrush="Black" Padding="0" >
<Border.Effect>
<DropShadowEffect x:Name="DSE" Color="Black" Direction="270" BlurRadius="20" ShadowDepth="3" Opacity="0.6" />
</Border.Effect>
<Border.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="DSE" Storyboard.TargetProperty="ShadowDepth" From="0" To="3" Duration="0:0:1" AutoReverse="False" />
<DoubleAnimation Storyboard.TargetName="DSE" Storyboard.TargetProperty="BlurRadius" From="0" To="20" Duration="0:0:1" AutoReverse="False" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<Grid Loaded="FrameworkElement_OnLoaded">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Name="Mask" CornerRadius="8" Background="White" />
<Grid x:Name="Grid" Background="White">
<Grid.OpacityMask>
<VisualBrush Visual="{Binding ElementName=Mask}"/>
</Grid.OpacityMask>
<StackPanel Name="StackPanel" >
<TextBox Style="{DynamicResource MaterialDesignTextBox}" Name="TitleBar" IsReadOnly="True" IsHitTestVisible="False" Padding="10" FontFamily="Segui" FontSize="14"
Foreground="Black" FontWeight="Normal"
Background="Yellow" HorizontalAlignment="Stretch" VerticalAlignment="Center" Width="Auto" HorizontalContentAlignment="Center" BorderThickness="0"/>
<DockPanel Name="ContentHost" Margin="0,10,0,10" >
<TextBlock Margin="10" Name="Textbar"></TextBlock>
</DockPanel>
<DockPanel Name="ButtonHost" LastChildFill="False" HorizontalAlignment="Center" >
<Button Margin="10" Click="ButtonBase_OnClick" Width="70">Yes</Button>
<Button Name="noBtn" Margin="10" Click="cancel_Click" Width="70">No</Button>
</DockPanel>
</StackPanel>
</Grid>
</Grid>
</Border>
</Window>
for cs of this file :
public partial class MessageboxNew : Window
{
public MessageboxNew()
{
InitializeComponent();
//second time show error solved
if (Application.Current == null) new Application();
Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
DialogResult = true;
}
private void cancel_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
}
private void FrameworkElement_OnLoaded(object sender, RoutedEventArgs e)
{
this.MouseDown += delegate { DragMove(); };
}
}
then create a class to use this :
public class Mk_MessageBox
{
public static bool? Show(string title, string text)
{
MessageboxNew msg = new MessageboxNew
{
TitleBar = {Text = title},
Textbar = {Text = text}
};
msg.noBtn.Focus();
return msg.ShowDialog();
}
}
now you can create your message box like this:
var result = Mk_MessageBox.Show("Remove Alert", "This is gonna remove directory from host! Are you sure?");
if (result == true)
{
// whatever
}
copy this to App.xaml inside
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
<!--two new guys-->
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.LightBlue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Green.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
-------------------------------
My Refrence :
https://www.red-gate.com/simple-talk/dotnet/net-development/using-c-to-create-powershell-cmdlets-the-basics/
for logic how can i make my own messagebox
As the others say, there is a MessageBox in the WPF namespace (System.Windows).
The problem is that it is the same old messagebox with OK, Cancel, etc. Windows Vista and Windows 7 have moved on to use Task Dialogs instead.
Unfortunately there is no easy standard interface for task dialogs. I use an implementation from CodeProject KB.
Maybe the code here below helps:
using Windows.UI.Popups;
namespace something.MyViewModels
{
public class TestViewModel
{
public void aRandonMethode()
{
MyMessageBox("aRandomMessage");
}
public async void MyMessageBox(string mytext)
{
var dialog = new MessageDialog(mytext);
await dialog.ShowAsync();
}
}
}

Resizing window with menu

I've come across a problem with making menus within a re-sizeable window. I've made a test app to demonstrate my problem below:
I'm animating a settings menu that transitions down from the top by changing the grid margin. When the settings menu is pushed above the window by changing the margin, if I resize the window height I can see the hidden menu rather than seeing the main screen (green) extending.
How Can I change it so the main grid (green) extends rather than being able to see the hidden settings menu?
Code:
<Window x:Class="ResizeTest.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:ResizeTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
MinWidth="800"
MinHeight="450"
MaxWidth="800"
MaxHeight="900">
<Window.Resources>
<Storyboard x:Key="ShowRightMenu">
<ThicknessAnimation Storyboard.TargetProperty="Margin"
Storyboard.TargetName="gridMenu"
From="0, -450, 0, 450"
To="0"
DecelerationRatio="0.9"
Duration="0:0:1" />
</Storyboard>
<Storyboard x:Key="HideRightMenu">
<ThicknessAnimation Storyboard.TargetProperty="Margin"
Storyboard.TargetName="gridMenu"
From="0"
To="0, -450, 0, 450"
DecelerationRatio="0.9"
Duration="0:0:1" />
</Storyboard>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Background="Green">
</Grid>
<Grid x:Name="gridMenu" Background="Blue"
Margin="0, -450, 0, 450"
Grid.Column="1">
<TextBlock Text="Well hello there!" Foreground="White" FontSize="60"
VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>
<Button HorizontalAlignment="Left" Width="100" Height="50" Margin="10" Content="Clicky Me"
Click="Button_Click" />
</Grid>
</Window>
I would suggest that you change the To and From Properties of the ThicknessAnimation so that it is up-to-date with the height of the window. And additionaly that at the start of an animation you set the Visibility of the menu to Visible and at the end to Collapsed if the menu should not be visible at the moment.
For this I would suggest that you add a field that holds the openness state of the menu
private bool menuOpen = false;
And alter one of the stroyboards to this
<Storyboard x:Key="MenuStoryboard">
<ThicknessAnimation Storyboard.TargetProperty="Margin"
Storyboard.TargetName="gridMenu"
DecelerationRatio="0.9"
Duration="0:0:1" />
</Storyboard>
and remove the other.
You should also remove the margin of the Grid and add Collapsed as a default Visibility
<Grid x:Name="gridMenu" Background="Blue"
Visibility="Collapsed"
Grid.Column="1">
...
</Grid>
And then in the Click-Event-Handler you can adjust the Storyboard to the situation and run the animation.
private void Button_Click(object sender, RoutedEventArgs e)
{
var storyBoard = this.FindResource("ShowRightMenu") as Storyboard;
var animation = storyBoard.Children[0] as ThicknessAnimation;
if (menuOpen)
{
animation.To = new Thickness(0, -this.Height, 0, Height);
animation.From = new Thickness(0);
}
else
{
animation.From = new Thickness(0, -this.Height, 0, this.Height);
animation.To = new Thickness(0);
}
this.gridMenu.Visibility = Visibility.Visible;
storyBoard.Begin();
void animationCompleated(object sender2, EventArgs e2)
{
if (!menuOpen)
{
this.gridMenu.Visibility = Visibility.Collapsed;
}
storyBoard.Completed -= animationCompleated;
}
storyBoard.Completed += animationCompleated;
menuOpen = !menuOpen;
}

My WPF ChromeWindow is slightly off when maximized

So I built this sample application and using a custom WindowChrome with WPF and C#. Everytime I try to maximize my window using the buttons I made, the maximized window becomes slightly off? Like by a few pixels. What is happening?
<Window x:Class="TestApp.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:TestApp"
mc:Ignorable="d"
Title="TestApp"
WindowStyle="None"
WindowStartupLocation="CenterScreen"
MinHeight="500" MinWidth="940">
<WindowChrome.WindowChrome>
<WindowChrome
ResizeBorderThickness="6"
CaptionHeight="20"
GlassFrameThickness="0"
CornerRadius="0"
/>
</WindowChrome.WindowChrome>
<!-- Application -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="26" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- WindowChrone Header -->
<Grid Background="{StaticResource WindowChromeBrush}" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="RelayC" />
<Button Click="MinimizeWindow" Grid.Column="2" Style="{StaticResource WindowChromeButton}">
<Image Source="{StaticResource window_minimize_icon}"/>
</Button>
<Button Click="MaximizeWindow" Grid.Column="3" Style="{StaticResource WindowChromeButton}">
<Image Source="{StaticResource window_maximize_icon}" />
</Button>
<Button Click="CloseWindow" Grid.Column="4" Style="{StaticResource WindowChromeButton}">
<Image Source="{StaticResource window_close_icon}" />
</Button>
</Grid>
<!--- Main Content -->
<Grid Grid.Row="1">
</Grid>
</Grid>
</Window>
Here is my sample code for the Button Functions:
private void MinimizeWindow(object sender, RoutedEventArgs e) => this.WindowState = WindowState.Minimized;
private void MaximizeWindow(object sender, RoutedEventArgs e) => this.WindowState = WindowState.Maximized;
private void CloseWindow(object sender, RoutedEventArgs e) => this.Close();
What am I doing wrong?
I ended up finding a sort of elegant solution to this problem. I simply assigned a name to the outermost grid, detected whenever it was maximized and added a margin to make sure the application was fully encompassing the screen and not going over. Then, when the screen size changed, I would remove said margin.
Here is some of my code:
Main functions:
private bool isMaximized = false;
private void CheckMaximizeChange(object sender, SizeChangedEventArgs e)
{
if (WindowState == WindowState.Maximized || (isMaximized && WindowState != WindowState.Minimized)) ChangeWindow();
}
private void MaximizeWindow(object sender, RoutedEventArgs e) => this.WindowState ^= WindowState.Maximized;
private void ChangeWindow()
{
isMaximized = !isMaximized;
MaximizeImageButton.Source = FindResource(MaximizeImageButton.Source == FindResource("window_maximize_icon") ? "window_restore_icon" : "window_maximize_icon") as DrawingImage;
MainGrid.Margin = new Thickness(MainGrid.Margin == new Thickness(0) ? 7 : 0);
}
then in the constructor of the application:
SizeChanged += CheckMaximizeChange;

Set button margin with auto window size

I've created a simple custom messagebox that automatically scales depending on the length of the text to be displayed :
public partial class CustomMessageBox : Window
{
public CustomMessageBox(string title, string text)
{
InitializeComponent();
ResizeMode = ResizeMode.NoResize;
label.Content = text;
Title = title;
}
public static void Show(string title, string text)
{
CustomMessageBox box = new CustomMessageBox(title, text);
box.SizeToContent = SizeToContent.WidthAndHeight;
box.ShowDialog();
}
private void button_Click(object sender, RoutedEventArgs e)
{
Close();
}
}
This works nicely however my button is clamping to the bottom side of the window because the window automatically scales :
And the button seems to be moving once the message gets longer :
How would I make sure the button stays centered and have a margin of around 10px from the bottom so it doesn't look that clamped?
I tried to set the Margin manually but that doesn't seem to work.
XAML (largely generated by the designer) :
<Window x:Class="RapidEvent.CustomMessageBox"
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:RapidEvent"
mc:Ignorable="d"
Background="{DynamicResource WindowBackgroundBrush}"
Title="" Height="Auto" Width="Auto">
<Grid>
<StackPanel>
<Label x:Name="label" Content="" HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Top" FontSize="13px" RenderTransformOrigin="0.392,0.486"/>
<Button x:Name="button" x:FieldModifier="public" IsDefault="True" Content="_Ok" HorizontalAlignment="Left" Margin="110,40,0,0" VerticalAlignment="Top" Width="80" Height="21" Click="button_Click"/>
</StackPanel>
</Grid>
</Window>
Simply change your StackPanel to a Grid and the HorizonalAlignment of your button to Center and take off all but the bottom margin. You'll also need to set the VerticalAlignment to Bottom. You also need to put the button on row 1.
This way the button will be clamped to the bottom of the dialog and always centred.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label x:Name="label" Content=""
HorizontalAlignment="Left" Margin="10,0,0,0"
VerticalAlignment="Top" FontSize="13px"
RenderTransformOrigin="0.392,0.486"/>
<Button Grid.Row="1" x:Name="button" x:FieldModifier="public"
IsDefault="True" Content="_Ok"
HorizontalAlignment="Center" Margin="0,0,0,20"
VerticalAlignment="Bottom" Width="80" Height="21"/>
</Grid>
Use grid instead of StackPanel:
<Grid >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<telerik:Label x:Name="label" Content="LSFFD" HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Top" FontSize="13px" RenderTransformOrigin="0.392,0.486"/>
<Button Grid.Row="1" x:Name="button" x:FieldModifier="public" Content="_Ok" HorizontalAlignment="Center" Margin="0 0 0 10" VerticalAlignment="Bottom" Width="80" Height="21" Click="button_Click"/>
</Grid>

How do I change the Textblock value on my splash screen?

I'm trying to make an animated splash screen for my app. I have my MainPage where I show a Popup which has an animation and a textblock. I'd like to change the text of my textblock to show the status of the loading, but I can't change it. Any ideas?
Mainpage code
namespace animatedsplash
{
public partial class MainPage : PhoneApplicationPage
{
BackgroundWorker preloader;
Popup splashPop;
public MainPage()
{
InitializeComponent();
splashPop = new Popup(){IsOpen = true, Child = new Splash() };
preloader = new BackgroundWorker();
RunPreloader();
}
private void RunPreloader()
{
preloader.DoWork += ((s, args) => {
Thread.Sleep(10000);
});
preloader.RunWorkerCompleted += ((s,args) =>
{
this.Dispatcher.BeginInvoke(()=> { this.splashPop.IsOpen = false; });
});
preloader.RunWorkerAsync();
}
}
}
Splash xaml
<phone:PhoneApplicationPage
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:ec="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions" xmlns:eim="clr-namespace:Microsoft.Expression.Interactivity.Media;assembly=Microsoft.Expression.Interactions"
xmlns:local="clr-namespace:animatedsplash"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
x:Class="animatedsplash.Splash"
Orientation="Portrait"
shell:SystemTray.IsVisible="False">
<phone:PhoneApplicationPage.Resources>
<Storyboard x:Name="load">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)" Storyboard.TargetName="image">
<EasingDoubleKeyFrame KeyTime="0" Value="-180"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="180"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</phone:PhoneApplicationPage.Resources>
<phone:PhoneApplicationPage.FontFamily>
<StaticResource ResourceKey="PhoneFontFamilyNormal"/>
</phone:PhoneApplicationPage.FontFamily>
<phone:PhoneApplicationPage.FontSize>
<StaticResource ResourceKey="PhoneFontSizeNormal"/>
</phone:PhoneApplicationPage.FontSize>
<phone:PhoneApplicationPage.Foreground>
<StaticResource ResourceKey="PhoneForegroundBrush"/>
</phone:PhoneApplicationPage.Foreground>
<i:Interaction.Triggers>
<eim:StoryboardCompletedTrigger Storyboard="{StaticResource load}">
<eim:ControlStoryboardAction Storyboard="{StaticResource load}"/>
</eim:StoryboardCompletedTrigger>
<i:EventTrigger>
<eim:ControlStoryboardAction Storyboard="{StaticResource load}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<!--TitlePanel contains the name of the application and page title--><!--ContentPanel - place additional content here-->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Image Margin="0" Grid.Row="1" Source="/media/splashbg.jpg" Stretch="Fill" d:IsLocked="True"/>
<Image x:Name="rotator" Margin="96,288,184,312" Grid.Row="1" Source="media/splashpin.png" Stretch="Fill" d:IsLocked="True"/>
<Image x:Name="image" Margin="142,305,0,370" Grid.Row="1" Source="media/pinload.png" Stretch="Fill" HorizontalAlignment="Left" Width="75" RenderTransformOrigin="0.838,0.504">
<Image.RenderTransform>
<CompositeTransform/>
</Image.RenderTransform>
</Image>
<TextBlock x:Name="preloader_percentage" Margin="178,354,0,0" Grid.Row="1" TextWrapping="Wrap" Text="100" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.593" TextAlignment="Right" HorizontalAlignment="Left" Width="35" FontFamily="Segoe WP Semibold" Height="27"/>
<TextBlock Margin="213,354,0,0" Grid.Row="1" TextWrapping="Wrap" Text="%" VerticalAlignment="Top" HorizontalAlignment="Left" Width="16" FontFamily="Segoe WP Semibold" d:IsLocked="True"/>
</Grid>
</phone:PhoneApplicationPage>
How about something like this:
In Splash.xaml.cs you would have the following:
public string Progress
{
get { return preloader_percentage.Text; }
set { preloader_percentage.Text = value; }
}
And in MainWindow.xaml.cs you change your code to look something like this:
preloader.WorkerReportsProgress = true;
preloader.ProgressChanged += (sender, e) =>
{
this.Dispatcher.BeginInvoke(() =>
(this.splashPop.Child as Splash).Progress = e.ProgressPercentage.ToString());
};
Then in your worker method you need to call preloader.ReportProgress() method several times. As far as I know, that should do it.
Note: There are a lot of design landmines here. I'd suggest getting this code to work, and you can refactor later to make it cleaner and easier to maintain.

Categories