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
Related
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.
I have created a custom water mark text box which is extended from text box. control template for the same is shown below.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:WaterMarkTextBox}">
<ControlTemplate.Resources>
<Storyboard x:Key="Storyboard1">
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)"
Storyboard.TargetName="PART_FieldTextBlock">
<SplineThicknessKeyFrame KeyTime="0:0:0.15"
Value="0,0,10,0" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard2">
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)"
Storyboard.TargetName="PART_FieldTextBlock">
<SplineThicknessKeyFrame KeyTime="0:0:0.25"
Value="0,0,-500,0" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid x:Name="PART_GridControl"
ClipToBounds="True"
Height="{TemplateBinding Height}"
Width="{TemplateBinding Width}">
<TextBlock x:Name="PART_PlaceHolderTextBlock"
Style="{StaticResource SWMLightTextBlockStyle}"
Foreground="#BDBBBB"
FontSize="{StaticResource SmallFontSize}"
Text="{TemplateBinding PlaceHolderText}"
VerticalAlignment="Center"
Margin="20,0,10,0" />
<Border Name="border"
CornerRadius="0"
Padding="2"
BorderThickness="1"
BorderBrush="DeepSkyBlue">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
<TextBlock x:Name="PART_FieldTextBlock"
HorizontalAlignment="Right"
Foreground="#BDBBBB"
Margin="0,0,-500,0"
Style="{StaticResource SWMLightTextBlockStyle}"
FontSize="{StaticResource SmallFontSize}"
TextWrapping="Wrap"
Text="{TemplateBinding FieldText}"
VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
but while typing the textbox enters to a condition where it is having no cursor but we can type into it occurs with a probability of 1/2 chars.I wonder how it happens. Anyone is having idea how it is happening?
Two things You can do. First One is Overriding SystemParameters Properties Using reflection Like this
void LocallyDisableMouseVanish()
{
foreach (var field in typeof(SystemParameters).GetFields(BindingFlags.NonPublic|BindingFlags.Static))
if (field.Name.Contains("mouseVanish"))
field.SetValue(null, false);
}
Call this method On Focus Of your Control.
If this is Not working means You can Try something Like this Override the style of the Caret Like this
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:WaterMarkTextBox}">
<ControlTemplate.Resources>
<Storyboard x:Key="Storyboard1">
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)"
Storyboard.TargetName="PART_FieldTextBlock">
<SplineThicknessKeyFrame KeyTime="0:0:0.15"
Value="0,0,10,0" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard2">
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)"
Storyboard.TargetName="PART_FieldTextBlock">
<SplineThicknessKeyFrame KeyTime="0:0:0.25"
Value="0,0,-500,0" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid x:Name="PART_GridControl"
ClipToBounds="True"
Height="{TemplateBinding Height}"
Width="{TemplateBinding Width}">
<TextBlock x:Name="PART_PlaceHolderTextBlock"
Style="{StaticResource SWMLightTextBlockStyle}"
Foreground="#BDBBBB"
FontSize="{StaticResource SmallFontSize}"
Text="{TemplateBinding PlaceHolderText}"
VerticalAlignment="Center"
Margin="20,0,10,0" />
<Border Name="border"
CornerRadius="0"
Padding="2"
BorderThickness="1"
BorderBrush="DeepSkyBlue">
<ScrollViewer x:Name="PART_ContentHost" />
</Border>
<TextBlock x:Name="PART_FieldTextBlock"
HorizontalAlignment="Right"
Foreground="#BDBBBB"
Margin="0,0,-500,0"
Style="{StaticResource SWMLightTextBlockStyle}"
FontSize="{StaticResource SmallFontSize}"
TextWrapping="Wrap"
Text="{TemplateBinding FieldText}"
VerticalAlignment="Center" />
<Canvas>
<Border x:Name="PART_Caret"
Visibility="Collapsed"
Canvas.Left="0"
Canvas.Top="0"
Width="5"
Height="25"
Background="Black"
BorderThickness="1">
<Border.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard x:Name="CaretStoryBoard"
RepeatBehavior="Forever">
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="Background.Color"
Duration="0:0:0:1"
FillBehavior="HoldEnd">
<ColorAnimationUsingKeyFrames.KeyFrames>
<DiscreteColorKeyFrame KeyTime="0:0:0.750"
Value="Transparent" />
<DiscreteColorKeyFrame KeyTime="0:0:0.000"
Value="Black" />
</ColorAnimationUsingKeyFrames.KeyFrames>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
</Border>
</Canvas>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="CaretBrush "
Value="Transparent" />
And in your control code Add this
public override void OnApplyTemplate()
{
this.border = this.GetTemplateChild("PART_Caret") as Border;
base.OnApplyTemplate();
}
And add this Method
private void MoveCustomCaret()
{
var caretLocation = this.GetRectFromCharacterIndex(this.CaretIndex).Location;
if (!double.IsInfinity(caretLocation.X))
{
Canvas.SetLeft(border, caretLocation.X);
}
if (!double.IsInfinity(caretLocation.Y))
{
Canvas.SetTop(border, caretLocation.Y);
}
}
And Finally Call This method and set the visibility of the border
private void SWMTextBox_GotFocus(object sender, RoutedEventArgs e)
{
MoveCustomCaret();
border.Visibility = Visibility.Visible;
}
also in TextChangedEvent
private void CustomTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
MoveCustomCaret();
}
And Hid the Visibility in Lost_Focus_Event
private void SWMTextBox_LostFocus(object sender, RoutedEventArgs e)
{
border.Visibility = Visibility.Hidden;
}
I'm trying to cobble together examples of listbox items on a (rendered via canvas) that expand in size when clicked. I'm close but the items move when zoomed, I would like them to zoom from the center and stay in place. Here is sample data collection.
public class Item
{
public double X { get; set; }
public double Y { get; set; }
public string Name { get; set; }
public string Color { get; set; }
}
public class ItemsFactory
{
private List<Item> items;
public IEnumerable<Item> Items
{
get
{
return items ?? (items = new List<Item>()
{
new Item { Name = "One", X = 100, Y = 100, Color="Red" },
new Item { Name = "Two", X = 88, Y = 210, Color="Green" },
new Item { Name = "Three", X = 200, Y = 295, Color="Blue" }
});
}
}
}
And below is my WPF. Items get bigger when clicked but they also move. I have tried RenderTransformOrigin in various places with no luck.
<Window x:Class="WPFCards.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFCards"
Title="MainWindow" Height="395.268" Width="607.807" Background="Black" WindowStyle="None" WindowState="Maximized">
<Window.Resources>
<local:ItemsFactory x:Key="sampleItems" />
</Window.Resources>
<Grid DataContext="{StaticResource sampleItems}">
<ListBox ItemsSource="{Binding Items}"
Background="Black"
SelectionMode="Multiple" >
<ListBox.ItemTemplate>
<DataTemplate>
<Canvas>
<Canvas.RenderTransform>
<ScaleTransform x:Name="st" ScaleY="{Binding ScaleX, RelativeSource={RelativeSource Self}}" />
</Canvas.RenderTransform>
<Grid
Canvas.Left="{Binding X}" Canvas.Top="{Binding Y}">
<Ellipse Fill="{Binding Color}" Width="50" Height="40" />
<ContentPresenter Content="{Binding Name}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Canvas>
<DataTemplate.Resources>
<CubicEase x:Key="ease" EasingMode="EaseOut"/>
</DataTemplate.Resources>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:0.3"
EasingFunction="{StaticResource ease}"
Storyboard.TargetName="st"
Storyboard.TargetProperty="ScaleX"
To="2"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:0.3"
EasingFunction="{StaticResource ease}"
Storyboard.TargetName="st"
Storyboard.TargetProperty="ScaleX"
To="1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
RenderTransform should be applied on ellipse container i.e. Grid and not on Canvas. Setting it on canvas is increasing the width and height of grid and hence affecting layout of ellipses in it.
Also, in case you want centric zoom, set RenderTransformOrigin="0.5,0.5" on Grid.
<Canvas>
<Grid Canvas.Left="{Binding X}" Canvas.Top="{Binding Y}"
RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<ScaleTransform x:Name="st"
ScaleY="{Binding ScaleX,
RelativeSource={RelativeSource Self}}"/>
</Grid.RenderTransform>
<Ellipse Fill="{Binding Color}" Width="50" Height="40" />
<ContentPresenter Content="{Binding Name}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Canvas>
A bit of guessing: I think you should set
RenderTransformOrigin="0.5,0.5"
of your Canvas
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.
I have a WPF window with property WindowStyle="SingleBorderWindow".
Now I want to know how to set a button on left upper corner of the window border.
You probably need to use window chrome library which is described here.
I assume this is so you can re-create the Minimize/Maximize/Close buttons.
You have two options, use a Grid or a DockPanel. I have included a sample for a Grid below.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="2,0" HorizontalAlignment="Right" VerticalAlignment="Top">
</StackPanel>
</Grid>
A Grid with a RowDefinition Height="Auto" that has a StackPanel Orientation="Horizontal" that is right-aligned.
However
If you want to make a true border-less window, you will have more work to do than simply setting the WindowStyle to None.
One main stumbling block I encountered was that when WindowStyle is None, it will not respect the task bar (i.e. overlap it) and you will need to hook into the message pump to set the correct window constraints.
Let me know in the comments if you want to know how to do this, will happy post sample code.
You need to make custom window by setting transparency, background and style like below :
<Window x:Class="WpfApplication2.Window2"
Name="Window2xx"
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"
mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Title="window1"
xmlns:m="clr-namespace:WpfApplication2"
AllowsTransparency="True" WindowStyle="None"
WindowStartupLocation="CenterOwner" d:DesignWidth="410" StateChanged="Window_StateChanged"
SizeToContent="WidthAndHeight" ShowInTaskbar="False" Background="Transparent">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Style.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<m:MasterWindow Width="400">
<m:MasterWindow.WindowTitle>
<ContentPresenter Content="window1" MouseLeftButtonDown="Window_MouseLeftButtonDown"></ContentPresenter>
</m:MasterWindow.WindowTitle>
<m:MasterWindow.Content>
<Grid>
</Grid>
</m:MasterWindow.Content>
</m:MasterWindow>
</Grid>
</Window>
Code behind window2 :
namespace WpfApplication2
{
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
private void Window_StateChanged(object sender, EventArgs e)
{
if (((Window)sender).WindowState == WindowState.Maximized)
((Window)sender).WindowState = WindowState.Normal;
}
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
try
{
DragMove();
}
catch ()
{}
}
}
}
Master window is like below :
namespace WpfApplication2
{
public class MasterWindow : ContentControl
{
public static RoutedCommand CloseWindowCommand;
static MasterWindow()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MasterWindow), new FrameworkPropertyMetadata(typeof(MasterWindow)));
CloseWindowCommand = new RoutedCommand("CloseWindow", typeof(MasterWindow));
CommandManager.RegisterClassCommandBinding(typeof(MasterWindow), new CommandBinding(CloseWindowCommand, CloseWindowEvent));
}
public static readonly DependencyProperty WindowTitleProperty = DependencyProperty.Register("WindowTitle", typeof(object), typeof(MasterWindow), new UIPropertyMetadata());
public object WindowTitle
{
get { return (object)GetValue(WindowTitleProperty); }
set { SetValue(WindowTitleProperty, value); }
}
private static void CloseWindowEvent(object sender, ExecutedRoutedEventArgs e)
{
MasterWindow control = sender as MasterWindow;
if (control != null)
{
Window objWindow = Window.GetWindow(((FrameworkElement)sender));
if (objWindow != null)
{
if (objWindow.Name.ToLower() != "unlockscreenwindow")
{
Window.GetWindow(((FrameworkElement)sender)).Close();
}
}
}
}
}
}
Styles for master window :
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:local="clr-namespace:WpfApplication2"
x:Class="MasterWindow">
<Style x:Key="WindowTitle" TargetType="ContentPresenter">
<Setter Property="Control.FontFamily" Value="Segoe UI"></Setter>
<Setter Property="Control.FontSize" Value="14"></Setter>
<Setter Property="Control.FontWeight" Value="SemiBold"></Setter>
<Setter Property="Control.Foreground" Value="White"></Setter>
<Setter Property="Control.VerticalAlignment" Value="Top"></Setter>
<Setter Property="Control.HorizontalAlignment" Value="Left"></Setter>
<Setter Property="Control.VerticalContentAlignment" Value="Top"></Setter>
</Style>
<Style x:Key="closebutton" BasedOn="{x:Null}" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Rectangle
Opacity="1"
RadiusX="2"
RadiusY="2"
Stroke="#ffffff"
StrokeThickness="1">
<Rectangle.Fill>
<LinearGradientBrush
StartPoint="0.6190476190476191,-0.5"
EndPoint="1.1128888811383928,1.426776123046875">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop
Color="#2E4C87"
Offset="0" />
<GradientStop
Color="#FFffffff"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Path
Margin="5,5,5,5"
Stretch="Fill"
Opacity="1"
Data="M 808.8311767578125,278.7662353515625 C808.8311767578125,278.7662353515625 820,268 820,268 "
Stroke="#ffffff"
StrokeThickness="2" />
<Path
Margin="5,5,5,5"
Stretch="Fill"
Opacity="1"
Data="M 809.4155883789062,268.3636474609375 C809.4155883789062,268.3636474609375 820,279 820,279 "
Stroke="#ffffff"
StrokeThickness="2" />
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True"/>
<Trigger Property="IsDefaulted" Value="True"/>
<Trigger Property="IsMouseOver" Value="True"/>
<Trigger Property="IsPressed" Value="True"/>
<Trigger Property="IsEnabled" Value="False"/>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:MasterWindow}">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MasterWindow}">
<StackPanel>
<Border x:Name="border" Background="WhiteSmoke" BorderBrush="#2E4C87" BorderThickness="7" CornerRadius="8,8,8,8" >
<Border.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Direction="320" Opacity="0.75" ShadowDepth="8"></DropShadowBitmapEffect>
</Border.BitmapEffect>
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="0.95" ScaleY="0.95"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Border.RenderTransform>
<Border.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" From="0" To="0.96" Duration="0:0:0.6"/>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" From="0" To="0.96" Duration="0:0:0.6"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<Grid HorizontalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition Height="32"></RowDefinition>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border BorderThickness="5,5,3,0" Background="#2E4C87" BorderBrush="#2E4C87" CornerRadius="5,4,0,0" VerticalAlignment="Top" Height="32" Margin="-6,-6,-4,0" >
<Grid Background="Transparent" HorizontalAlignment="Stretch" Height="32" VerticalAlignment="Center" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<ContentPresenter Content="{TemplateBinding WindowTitle}" Margin="0,4,0,0" HorizontalAlignment="Stretch" Style="{StaticResource WindowTitle}" />
<Button Name="btnClose" Style="{StaticResource closebutton}" Cursor="Hand" Command="{x:Static local:MasterWindow.CloseWindowCommand}" VerticalAlignment="Top" Height="18" HorizontalAlignment="Right" Width="18" Margin="0,5,8,0" Grid.Column="1" />
</Grid>
</Border>
<Border BorderBrush="Transparent" BorderThickness="7,0,7,7" VerticalAlignment="Top" HorizontalAlignment="Left" CornerRadius="0,0,10,10" Grid.Row="1"></Border>
<ContentPresenter Grid.Row="1" Content="{TemplateBinding Content}" VerticalAlignment="Top" Margin="0,-6,0,0"/>
</Grid>
</Border>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>