Closing Material Design DialogHost from Code - c#

I'm trying to find a way to initiate the close of an active DialogHost from code, but have been unable to find the right syntax. I think the main challenge is accessing the DialogHost from a class outside of the MainWindow code behind.
The entirety of my XAML:
<Window x:Class="MaterialDesignTest.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:MaterialDesignTest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextElement.FontWeight="Regular"
TextElement.FontSize="13"
TextOptions.TextFormattingMode="Ideal"
TextOptions.TextRenderingMode="Auto"
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{DynamicResource MaterialDesignFont}">
<materialDesign:DialogHost Identifier="RootDialog" Loaded="DialogHost_Loaded">
<Grid>
<StackPanel>
<Button Width="100" x:Name="SearchRestore" Margin="0 150 0 0" Command="{x:Static materialDesign:DialogHost.OpenDialogCommand}" materialDesign:DialogHost.DialogClosingAttached="SearchRestore_OnDialogClosing"
Content="Restore" Click="SearchRestore_Click">
<Button.CommandParameter>
<StackPanel Margin="10">
<TextBlock Text="Restoring..."/>
<Button Name="CircleButton" Margin="0 50 0 0" Style="{StaticResource MaterialDesignFloatingActionButton}"
Command="{Binding SaveComand}" IsHitTestVisible="False"
materialDesign:ButtonProgressAssist.IsIndicatorVisible="{Binding IsSaving}"
materialDesign:ButtonProgressAssist.Value="{Binding SaveProgressButton}">
<materialDesign:PackIcon Height="24" Width="24" Foreground="White">
<materialDesign:PackIcon.Style>
<Style TargetType="materialDesign:PackIcon" BasedOn="{StaticResource {x:Type materialDesign:PackIcon}}">
<Setter Property="Kind" Value="CloudSync" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsSaveComplete}" Value="True">
<Setter Property="Kind" Value="Check" />
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.8" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</materialDesign:PackIcon.Style>
</materialDesign:PackIcon>
</Button>
</StackPanel>
</Button.CommandParameter>
</Button>
</StackPanel>
</Grid>
</materialDesign:DialogHost>
And the code from which I need to initiate the close (this is in a view model, not the MainWindow code behind):
private async void progressTimerTick(object sender, EventArgs e)
{
if (progress < 100 && cycles < 2)
{
if (progress == 99)
{
cycles++;
progress = 0;
}
IsSaveComplete = false;
IsSaving = true;
progress++;
SaveProgressButton = progress;
}
else
{
IsSaveComplete = true;
IsSaving = false;
progressTimer.Enabled = false;
SaveProgressButton = 0;
await PutTaskDelay();
//Close dialog here
}
}

There are 3 ways to close a dialog in MDIX:
var dialogResult = await DialogHost.Show(myDialogControl, (sender, args) =>
{
args.Session.Close(false);
});
or
DialogHost.CloseDialogCommand.Execute(null,null);
or
DialogHostInstance.IsOpen = false;

Regarding #Talha answer.
I have tried your solution, however, it didn't work. On the other hand, I found a way to fix it:
var drawer = DrawerHost.CloseDrawerCommand;
drawer.Execute(null, null);
It looks the same, but worked for me.

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();
}
}
}

How to display current date and time on Wpf statusbar

I want to know how to display current date and time on a WPF statusbar.
I know this is too basic a question, but I am new to .net WPF,
and I know this can be done in a Form application easily.
Thanks in advance.
Ting
Create a wpf project. In your MainWindow.xaml add the StatusBar and handle Loaded event of window.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApp1.MainWindow"
Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StatusBar Grid.Row="1">
<TextBlock x:FieldModifier="private" x:Name="myDateTime"/>
</StatusBar>
</Grid>
</Window>
In the MainWindow.xaml.cs add the following namespaces (if they are not exist):
using System;
using System.Windows;
using System.Windows.Threading;
And in the Loaded enevt handler you can use DispatcherTimer for update textblock text property every second:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
DispatcherTimer timer = new DispatcherTimer(TimeSpan.FromSeconds(1), DispatcherPriority.Normal, (object s, EventArgs ev) =>
{
this.myDateTime.Text = DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss");
}, this.Dispatcher);
timer.Start();
}
Also there are a lot of examples for customize wpf controls using Template and Style properties. just search for it.
Styles and templates in WPF
The WPF StatusBar control
and many more.
Also you can implement your custom WPFTimer. This simple implementation get you an idea for do this.
public class WPFTimer : TextBlock
{
#region static
public static readonly DependencyProperty IntervalProperty = DependencyProperty.Register("Interval", typeof(TimeSpan), typeof(WPFTimer), new PropertyMetadata(TimeSpan.FromSeconds(1), IntervalChangedCallback));
public static readonly DependencyProperty IsRunningProperty = DependencyProperty.Register("IsRunning", typeof(bool), typeof(WPFTimer), new PropertyMetadata(false, IsRunningChangedCallback));
private static void IntervalChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
WPFTimer wpfTimer = (WPFTimer)d;
wpfTimer.timer.Interval = (TimeSpan)e.NewValue;
}
private static void IsRunningChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
WPFTimer wpfTimer = (WPFTimer)d;
wpfTimer.timer.IsEnabled = (bool)e.NewValue;
}
#endregion
private readonly DispatcherTimer timer;
[Category("Common")]
public TimeSpan Interval
{
get
{
return (TimeSpan)this.GetValue(IntervalProperty);
}
set
{
this.SetValue(IntervalProperty, value);
}
}
[Category("Common")]
public bool IsRunning
{
get
{
return (bool)this.GetValue(IsRunningProperty);
}
set
{
this.SetValue(IsRunningProperty, value);
}
}
public WPFTimer()
{
this.timer = new DispatcherTimer(this.Interval, DispatcherPriority.Normal,this.Timer_Tick ,this.Dispatcher);
this.timer.IsEnabled = false;
}
private void Timer_Tick(object sender, EventArgs e)
{
this.SetValue(TextProperty, DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss"));
}
}
And now you have a control that can use it in the designer.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1"
x:Class="WpfApp1.MainWindow"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StatusBar Grid.Row="1">
<local:WPFTimer IsRunning="True"/>
</StatusBar>
</Grid>
</Window>
You can do it this way, using wpf animation and binding, and no background code :)
<Window x:Class="WpfApp6.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:system="clr-namespace:System;assembly=System.Runtime"
mc:Ignorable="d"
Title="MainWindow"
Height="450"
Width="800">
<Grid>
<Grid.Resources>
<!--Set x: share to get the latest every time-->
<system:DateTime x:Key="DateTime"
x:Shared="False" />
<Storyboard x:Key="Storyboard">
<!--Use keyframe animation to update datetime -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="DataContext"
Duration="0:0:1"
RepeatBehavior="Forever"
AutoReverse="False">
<DiscreteObjectKeyFrame KeyTime="50%"
Value="{StaticResource DateTime}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Grid.Resources>
<!--Get datetime from DataContext-->
<TextBlock Text="{Binding RelativeSource={RelativeSource Self},Path=DataContext.Now}"
DataContext="{StaticResource DateTime}">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard Storyboard="{StaticResource Storyboard}" />
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
</Grid>
</Window>
or like this,a real clock
<Window x:Class="WpfApp6.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:system="clr-namespace:System;assembly=System.Runtime"
mc:Ignorable="d"
Title="MainWindow"
Height="450"
Width="800">
<Window.Resources>
<FrameworkElement x:Key="time" Tag="{x:Static system:DateTime.Now}" />
<TransformGroup x:Key="transformHour">
<TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Hour}"
Y="{Binding Source={StaticResource time},Path=Tag.Minute}" />
<MatrixTransform Matrix="30 0 0.5 0 0 0" />
</TransformGroup>
<TransformGroup x:Key="transformMinute">
<TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Minute}"
Y="{Binding Source={StaticResource time},Path=Tag.Second}" />
<MatrixTransform Matrix="6 0 0.1 0 0 0" />
</TransformGroup>
<TransformGroup x:Key="transformSecond">
<TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Second}" />
<MatrixTransform Matrix="6 0 0 0 0 0" />
</TransformGroup>
<Style TargetType="{x:Type Path}">
<Setter Property="Stroke"
Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Setter Property="StrokeThickness" Value="3" />
<Setter Property="StrokeDashCap" Value="Triangle" />
</Style>
</Window.Resources>
<Viewbox>
<Canvas Width="200" Height="200">
<Canvas.RenderTransform>
<TranslateTransform X="100" Y="100" />
</Canvas.RenderTransform>
<Path Data="M 0 -90 A 90 90 0 1 1 -0.01 -90"
StrokeDashArray="0 3.14157" />
<Path Data="M 0 -90 A 90 90 0 1 1 -0.01 -90"
StrokeDashArray="0 7.854"
StrokeThickness="6" />
<Border Background="LightBlue" Width="10" Height="80" RenderTransformOrigin="0.5 0">
<Border.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="bor_Second"
Angle="{Binding Source={StaticResource transformSecond},Path=Value.OffsetX}" />
<RotateTransform Angle="180" />
</TransformGroup>
</Border.RenderTransform>
</Border>
<Border Background="LightGreen" Width="10" Height="60" RenderTransformOrigin="0.5 0">
<Border.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="bor_Minute"
Angle="{Binding Source={StaticResource transformMinute},Path=Value.OffsetX}" />
<RotateTransform Angle="180" />
</TransformGroup>
</Border.RenderTransform>
</Border>
<Border Background="LightGray" Width="10" Height="40" RenderTransformOrigin="0.5 0">
<Border.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="bor_Hour"
Angle="{Binding Source={StaticResource transformHour},Path=Value.OffsetX}" />
<RotateTransform Angle="180" />
</TransformGroup>
</Border.RenderTransform>
</Border>
</Canvas>
</Viewbox>
<Window.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="bor_Hour"
Storyboard.TargetProperty="Angle"
IsAdditive="True"
Duration="12:0:0"
From="0" To="360"
RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="bor_Minute"
Storyboard.TargetProperty="Angle"
IsAdditive="True"
Duration="1:0:0"
From="0" To="360"
RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="bor_Second"
Storyboard.TargetProperty="Angle"
IsAdditive="True"
Duration="0:1:0"
From="0"
To="360"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
</Window>
Create a clock using only xaml code in wpf

UWP setting Grid.Column with style not working

I'm developing a UWP app and trying to apply a style per control in code that would set the Grid.Column property, effectively to move the elements around the grid. However, my elements stay where they are, even though the animations run. Any setter besides Grid.* works, and I can see the styles being applied both through my code and through the live property window.
I know there are other ways to accomplish what I'm going for and I'll probably do one of those, but I want to know what's going on here. I'll post a sample of my page and the command that applies the styling:
MainPage.xaml
<Page
x:Class="UWPApp.Scorekeeper.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UWPApp.Scorekeeper"
xmlns:viewmodels="using:UWPApp.Scorekeeper.Models.ViewModels"
xmlns:converters="using:UWPApp.Scorekeeper.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mo="using:UWPApp.Scorekeeper.Models"
mc:Ignorable="d"
x:Name="MainPageElement"
d:DesignHeight="600"
d:DesignWidth="1024">
<Page.Resources>
<DataTemplate x:Key="GridHorizontalTemplate" x:DataType="local:MainPage">
<Grid MinWidth="768" MinHeight="500" Background="{ThemeResource SystemControlBackgroundAccentBrush}" ManipulationMode="All">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="69*"/>
<ColumnDefinition Width="76*"/>
<ColumnDefinition Width="76*"/>
<ColumnDefinition Width="69*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="73*"/>
<RowDefinition Height="135*"/>
<RowDefinition Height="69*"/>
<RowDefinition Height="43*"/>
</Grid.RowDefinitions>
<Button Foreground="{ThemeResource SystemControlForegroundChromeMediumBrush}" Command="{Binding ElementName=MainPageElement, Path=EnterGoalCommand}" CommandParameter="{Binding ElementName=MainPageElement,Path=StateModel.HomeID}" x:Name="HomeGoalBtn" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="1" Grid.Column="1" Margin="0,0.4,0,0" d:LayoutOverrides="LeftMargin, RightMargin" >
<Button.Resources>
<Style x:Key="FlippedStyle" TargetType="Button">
<Setter Property="Grid.Column" Value="2"/>
</Style>
<Storyboard x:Key="ToFlipAnimation">
<RepositionThemeAnimation FromHorizontalOffset="-487"/>
</Storyboard>
<Storyboard x:Key="FromFlipAnimation">
<RepositionThemeAnimation FromHorizontalOffset="487"/>
</Storyboard>
</Button.Resources>
<Viewbox Margin="40" Stretch="Uniform">
<TextBlock Text="Goal" FontSize="48" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Bottom" />
</Viewbox>
</Button>
<Button Foreground="{ThemeResource SystemControlForegroundChromeMediumBrush}" Command="{Binding ElementName=MainPageElement, Path=EnterGoalCommand}" CommandParameter="{Binding ElementName=MainPageElement,Path=StateModel.AwayID}" x:Name="AwayGoalBtn" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="1" Grid.Column="2" Margin="0,0.4,-0.2,0" d:LayoutOverrides="LeftMargin, RightMargin" >
<Button.Resources>
<Style x:Key="FlippedStyle" TargetType="Button">
<Setter Property="Grid.Column" Value="1"/>
</Style>
<Storyboard x:Key="ToFlipAnimation">
<RepositionThemeAnimation FromHorizontalOffset="487"/>
</Storyboard>
<Storyboard x:Key="FromFlipAnimation">
<RepositionThemeAnimation FromHorizontalOffset="-487"/>
</Storyboard>
</Button.Resources>
<Viewbox Margin="40" Stretch="Uniform">
<TextBlock Text="Goal" FontSize="48" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Bottom" />
</Viewbox>
</Button>
</Grid>
</DataTemplate>
</Page.Resources>
<ContentPresenter x:Name="MainContent" Margin="0,0,0,0" HorizontalAlignment="Stretch" d:LayoutOverrides="Width, Height" VerticalAlignment="Stretch">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1000"></AdaptiveTrigger>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="MainContent.ContentTemplate" Value="{StaticResource GridHorizontalTemplate}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ContentPresenter>
</Page>
MainPage.xaml.cs
public ICommand FlipScreen => new CommandHandler(() =>
{
if (!flipped)
{
flipped = true;
foreach (var item in this.FindChildren<FrameworkElement>())
{
object styleObject;
if (item.Resources.TryGetValue("FlippedStyle", out styleObject))
{
item.Style = (Style)styleObject;
}
object animationObject;
if (item.Resources.TryGetValue("ToFlipAnimation", out animationObject))
{
Storyboard board = animationObject as Storyboard;
if (board.GetCurrentState() != ClockState.Stopped)
{
board.Stop();
}
foreach (var subitem in board.Children)
{
Storyboard.SetTarget(subitem, item);
}
board.Begin();
}
}
}
else
{
flipped = false;
foreach (var item in this.FindChildren<FrameworkElement>())
{
item.Style = null;
object animationObject;
if (item.Resources.TryGetValue("FromFlipAnimation", out animationObject))
{
Storyboard board = animationObject as Storyboard;
if (board.GetCurrentState() != ClockState.Stopped)
{
board.Stop();
}
foreach (var subitem in board.Children)
{
Storyboard.SetTarget(subitem, item);
}
board.Begin();
}
}
}
});
FindChildren:
public static List<T> FindChildren<T>(this FrameworkElement element) where T : FrameworkElement
{
int childrenCount = VisualTreeHelper.GetChildrenCount(element);
var children = new FrameworkElement[childrenCount];
List<T> list = new List<T>();
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(element, i) as FrameworkElement;
children[i] = child;
if (child is T)
list.Add(child as T);
}
for (int i = 0; i < childrenCount; i++)
if (children[i] != null)
{
var subChild = FindChildren<T>(children[i]);
if (subChild != null)
list.AddRange(subChild);
}
return list;
}
Not sure if a default Button Style in the Resources of a Button would actually apply to that Button.
Better set the Style explicitly:
<Button ... >
<Button.Style>
<Style TargetType="Button">
<Setter Property="Grid.Column" Value="2"/>
</Style>
</Button.Style>
<Button.Resources>
...
</Button.Resources>
<Viewbox ...>
...
</Viewbox>
</Button>

WPF application access controls in code-behind

I'm workin on a WPF scorekeeping app. So far the UI is done, but I can't access any of the controls in the code-behind. Here's the XAML:
<Window x:Class="Scoreboard.MainScoreBoard"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DartsLeague" Height="720" Width="1280">
<Grid x:Name="MainGrid" Background="DarkGreen">
<StackPanel x:Name="Player1" HorizontalAlignment="Left" VerticalAlignment="Stretch">
<Label x:Name="Player1Name" Style="{StaticResource PlayerName}"/>
<Label x:Name="Player1Score" Style="{StaticResource Score}"/>
<ScrollViewer x:Name="Player1Throws" Height="380" FlowDirection="RightToLeft">
</ScrollViewer>
</StackPanel>
<StackPanel x:Name="Player2" HorizontalAlignment="Right" VerticalAlignment="Stretch">
<Label x:Name="Player2Name" Style="{StaticResource PlayerName}">Player 2</Label>
<Label x:Name="Player2Score" Style="{StaticResource Score}">501</Label>
<ScrollViewer x:Name="Player2Throws" Height="380">
</ScrollViewer>
</StackPanel>
<StackPanel x:Name="Input" HorizontalAlignment="Center" VerticalAlignment="Top">
<TextBox x:Name="CurrentNumber" MaxLength="3" Width="160" Margin="20" FontSize="30" TextChanged="TextBox_TextChanged"></TextBox>
<Button x:Name="SubmitButton" IsDefault="True" Style="{StaticResource Golden} " Click="Button_Click">Запиши резултат</Button>
<Button x:Name="CancelButton" Style="{StaticResource Golden}">Върни назад</Button>
</StackPanel>
<Grid x:Name="StatsGrid" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="60" Width="560">
<StackPanel x:Name="Player1Stats" HorizontalAlignment="Left" VerticalAlignment="Stretch">
<Label x:Name="Player1Legs" Style="{StaticResource BoardStats}"/>
<Label x:Name="Player1Sets" Style="{StaticResource BoardStats}"/>
<Label x:Name="Player1Avr" Style="{StaticResource BoardStats}"/>
</StackPanel>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Stretch">
<Label Style="{StaticResource BoardStats}">LEGS</Label>
<Label Style="{StaticResource BoardStats}">SETS</Label>
<Label Style="{StaticResource BoardStats}">3 DART AVERAGE</Label>
</StackPanel>
<StackPanel x:Name="Player2Stats" HorizontalAlignment="Right" VerticalAlignment="Stretch">
<Label x:Name="Player2Legs" Style="{StaticResource BoardStats}"/>
<Label x:Name="Player2Sets" Style="{StaticResource BoardStats}"/>
<Label x:Name="Player2Avr" Style="{StaticResource BoardStats}"/>
</StackPanel>
</Grid>
</Grid>
</Window>
App.xaml:
<Application x:Class="Scoreboard.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Scoreboard"
StartupUri="StartWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<Style x:Key="Golden" TargetType="Button">
<Setter Property="Background" Value="Gold" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="Margin" Value="10" />
<Setter Property="Padding" Value="4" />
<Setter Property="FontSize" Value="30" />
</Style>
<Style x:Key="PlayerName" TargetType="Label">
<Setter Property="Background" Value="White" />
<Setter Property="Margin" Value="10"/>
<Setter Property="FontSize" Value="34" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style x:Key="Score" TargetType="Label">
<Setter Property="Margin" Value="10" />
<Setter Property="Background" Value="White" />
<Setter Property="FontSize" Value="160" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style x:Key="BoardStats" TargetType="Label">
<Setter Property="Background" Value="Beige" />
<Setter Property="Margin" Value="4" />
<Setter Property="BorderBrush" Value="DarkRed" />
<Setter Property="BorderThickness" Value="4" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="26" />
<Setter Property="Padding" Value="8" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
Heres the C# Code, It probably has more bugs that I know of, but it won't compile because it doesn't recognize any of the names from the XAML:
namespace Scoreboard
{
public partial class MainScoreBoard : Window
{
public MainScoreBoard()
{
InitializeComponent();
}
static bool IsTextAllowed(string text, int num)
{
Regex regex = new Regex("[^0-9.-]+");
if (!regex.IsMatch(text))
{
num = Int32.Parse(text);
return true;
}
else return false;
}
void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
}
void Button_Click(object sender, RoutedEventArgs e)
{
// You should get in the habit of initializing your variables
int currentScore = 0, currentPlayerScore, currentResult, legs, sets;
bool Player1Turn = true;
// You were getting null reference exceptions from attempting to access the Content property
// without them ever getting set. You can initialize them with default values in the xaml or in the
// constructor on initialization (After InitializeComponent() call).
if (Player1Score.Content != null && Player2Score.Content != null)
{
bool isGameOver = false;
// This will loop infinitely if you don't fix the bugs in calculating the score, I put a comment on it as you are not getting a value for currentScore from anywhere
while (Int32.Parse(Player1Score.Content.ToString()) != 0 || Int32.Parse(Player2Score.Content.ToString()) != 0)
{
if (IsTextAllowed(CurrentNumber.Text, currentScore))
{
if (currentScore > 180)
{
MessageBox.Show("Написаното е над 180!!!");
continue;
}
if (Player1Turn)
{
Player1Turn = false;
currentPlayerScore = Int32.Parse(Player1Score.Content.ToString());
// The currentScore variable is never getting set, I initialized it for you but
// it needs to be assigned a value from somewhere otherwise it will always be
// currentResult = currentPlayerScore - 0
currentResult = currentPlayerScore - currentScore;
if (currentResult < 0)
{
MessageBox.Show("Предобри!!!");
continue;
}
else if (currentResult == 0)
{
MessageBox.Show("Game Over!!!");
legs = Int32.Parse(Player1Legs.Content.ToString());
legs++;
Player1Legs.Content = legs.ToString();
if (legs == 3)
{
//increas sets
//if sets == 3, end game and shut down app
}
//Application.Current.Shutdown();
// Set flag so we do not keep looping through game over code
isGameOver = true;
}
Player1Score.Content = currentResult.ToString();
// Added this check here because I'm assuming you would want Player1Score to be reflected first
// before exiting the loop.
if (isGameOver)
{
// game is over, we do not want to keep showing the Game Over message box
break;
}
}
else
{
//the same for Player2
Player1Turn = true;
}
}
}
}
}
}
}
All of the controls have an x:Name on them, but I can access only 2 ot 3 of them, and even if I can, nothing happens. I want to write text in the textbox, and after some processing goes on with the textbox, some output and stats are supposed to show up on the labels, but it won't let me access any of it, or if it does, it's random, and nothing happens, as if there is no code there.
I cannot see the code for your Window declaration in the xaml. But since you renamed the namespace and class, you should have this in your xaml window declaration.
x:Class="Scoreboard.MainScoreBoard"
Essentially your xaml should look like this
<Window x:Class="Scoreboard.MainScoreBoard"
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>
You do have a lot more bugs in the code behind as you need to call .ToString() in several places as well as some null reference exceptions, but if you get stuck in there you can always post a new question.
public partial class MainScoreBoard : Window
{
public MainScoreBoard()
{
InitializeComponent();
}
static bool IsTextAllowed(string text, int num)
{
Regex regex = new Regex("[^0-9.-]+");
if (!regex.IsMatch(text))
{
num = Int32.Parse(text);
return true;
}
else return false;
}
void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
}
void Button_Click(object sender, RoutedEventArgs e)
{
// You should get in the habit of initializing your variables
int currentScore = 0, currentPlayerScore, currentResult, legs, sets;
bool Player1Turn = true;
// You were getting null reference exceptions from attempting to access the Content property
// without them ever getting set. You can initialize them with default values in the xaml or in the
// constructor on initialization (After InitializeComponent() call).
if (Player1Score.Content != null && Player2Score.Content != null)
{
bool isGameOver = false;
// This will loop infinitely if you don't fix the bugs in calculating the score, I put a comment on it as you are not getting a value for currentScore from anywhere
while (Int32.Parse(Player1Score.Content.ToString()) != 0 || Int32.Parse(Player2Score.Content.ToString()) != 0)
{
if (IsTextAllowed(CurrentNumber.Text, currentScore))
{
if (currentScore > 180)
{
MessageBox.Show("Написаното е над 180!!!");
continue;
}
if (Player1Turn)
{
Player1Turn = false;
currentPlayerScore = Int32.Parse(Player1Score.Content.ToString());
// The currentScore variable is never getting set, I initialized it for you but
// it needs to be assigned a value from somewhere otherwise it will always be
// currentResult = currentPlayerScore - 0
currentResult = currentPlayerScore - currentScore;
if (currentResult < 0)
{
MessageBox.Show("Предобри!!!");
continue;
}
else if (currentResult == 0)
{
MessageBox.Show("Game Over!!!");
legs = Int32.Parse(Player1Legs.Content.ToString());
legs++;
Player1Legs.Content = legs.ToString();
if (legs == 3)
{
//increas sets
//if sets == 3, end game and shut down app
}
//Application.Current.Shutdown();
// Set flag so we do not keep looping through game over code
isGameOver = true;
}
Player1Score.Content = currentResult.ToString();
// Added this check here because I'm assuming you would want Player1Score to be reflected first
// before exiting the loop.
if (isGameOver)
{
// game is over, we do not want to keep showing the Game Over message box
break;
}
}
else
{
//the same for Player2
Player1Turn = true;
}
}
}
}
}
}
Those styles in the xaml are not defined anywhere you should remove them until you implement the styles. I removed them when compiling as they are not defined.
<Window x:Class="Scoreboard.MainScoreBoard"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Scoreboard"
Title="DartsLeague" Height="720" Width="1280">
<Grid x:Name="MainGrid" Background="DarkGreen">
<StackPanel x:Name="Player1" HorizontalAlignment="Left" VerticalAlignment="Stretch">
<Label x:Name="Player1Name"/>
<Label x:Name="Player1Score">501</Label>
<ScrollViewer x:Name="Player1Throws" Height="380" FlowDirection="RightToLeft">
</ScrollViewer>
</StackPanel>
<StackPanel x:Name="Player2" HorizontalAlignment="Right" VerticalAlignment="Stretch">
<Label x:Name="Player2Name">Player 2</Label>
<Label x:Name="Player2Score">501</Label>
<ScrollViewer x:Name="Player2Throws" Height="380">
</ScrollViewer>
</StackPanel>
<StackPanel x:Name="Input" HorizontalAlignment="Center" VerticalAlignment="Top">
<TextBox x:Name="CurrentNumber" MaxLength="3" Width="160" Margin="20" FontSize="30" TextChanged="TextBox_TextChanged"></TextBox>
<Button x:Name="SubmitButton" IsDefault="True" Click="Button_Click">Запиши резултат</Button>
<Button x:Name="CancelButton">Върни назад</Button>
</StackPanel>
<Grid x:Name="StatsGrid" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="60" Width="560">
<StackPanel x:Name="Player1Stats" HorizontalAlignment="Left" VerticalAlignment="Stretch">
<Label x:Name="Player1Legs">0</Label>
<Label x:Name="Player1Sets" />
<Label x:Name="Player1Avr" />
</StackPanel>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Stretch">
<Label>LEGS</Label>
<Label>SETS</Label>
<Label>3 DART AVERAGE</Label>
</StackPanel>
<StackPanel x:Name="Player2Stats" HorizontalAlignment="Right" VerticalAlignment="Stretch">
<Label x:Name="Player2Legs"/>
<Label x:Name="Player2Sets"/>
<Label x:Name="Player2Avr" />
</StackPanel>
</Grid>
</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