I am trying to figure out how to best use WPF's HandOffBehavior technique. Right now, I have a scrolling error marquee in my application that animates opening up, scrolling the error message, and then closing itself.
I was just starting to build this WPF application this week. The problem is that I can't seem to gracefully prepare for a scenario like when the user clicks the Login button twice or more times in small consecutive intervals. I would like to see the error marquee only continue sending the error text across the screen when the user commits such behavior with the login button rather than open and close the marquee multiple redundant times, etc. Here's the relevant code.
MainWindow.xaml.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data.Entity;
using System.Windows.Media.Animation;
using PasswordHash;
namespace ChatClient
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void logIn(object sender, RoutedEventArgs e)
{
string nameRecord = "";
string passRecord = "";
if (UsernameField.Text == "" || UserPassField.Password == "")
{
openErrorMarquee("Username and password required");
}
else
{
using (otongadgethubEntities logCheck = new otongadgethubEntities())
{
var userNullCheck = logCheck.users.FirstOrDefault(a => a.username == UsernameField.Text);
if (userNullCheck == null)
{
openErrorMarquee("Username does not exist");
}
if (userNullCheck != null)
{
nameRecord = userNullCheck.username;
}
if (nameRecord == UsernameField.Text)
{
passRecord = Encrypt.MD5(UserPassField.Password).ToLower();
if (passRecord == userNullCheck.password)
{
//Yay! User logged in!
}
else
{
openErrorMarquee("Password invalid");
}
}
}
}
}
private void openErrorMarquee(string errorMessage)
{
errorMarquee.Visibility = System.Windows.Visibility.Visible;
DoubleAnimation openMarquee = new DoubleAnimation();
openMarquee.From = 0;
openMarquee.To = 17;
openMarquee.Duration = new Duration(TimeSpan.FromSeconds(1.0));
openMarquee.Completed += (s, doneEvent) => errorMarqueeScroll(errorMessage);
errorMarquee.BeginAnimation(Rectangle.HeightProperty, openMarquee, HandoffBehavior.Compose);
}
private void errorMarqueeScroll(string errorMessage)
{
errorText.Text = errorMessage;
errorText.Visibility = System.Windows.Visibility.Visible;
double height = errorCanvas.ActualHeight - errorText.ActualHeight;
errorText.Margin = new Thickness(0, height / 2, 0, 0);
DoubleAnimation doubleErrorAnimation = new DoubleAnimation();
doubleErrorAnimation.From = -errorText.ActualWidth;
doubleErrorAnimation.To = errorCanvas.ActualWidth;
//doubleErrorAnimation.RepeatBehavior = RepeatBehavior.Forever;
doubleErrorAnimation.Completed += new EventHandler(closeErrorMarquee);
doubleErrorAnimation.Duration = new Duration(TimeSpan.FromSeconds(7.0));
errorText.BeginAnimation(Canvas.RightProperty, doubleErrorAnimation);
}
private void closeErrorMarquee(object sender, EventArgs e)
{
DoubleAnimation closeMarquee = new DoubleAnimation();
closeMarquee.From = 17;
closeMarquee.To = 0;
closeMarquee.Duration = new Duration(TimeSpan.FromSeconds(1.0));
closeMarquee.Completed += (s, doneEvent) => {
errorMarquee.Visibility = System.Windows.Visibility.Hidden;
errorText.Visibility = System.Windows.Visibility.Hidden;
};
errorMarquee.BeginAnimation(Rectangle.HeightProperty, closeMarquee, HandoffBehavior.Compose);
}
}
}
And here's the XAML for those that need to see the window too:
<Window
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" x:Class="ChatClient.MainWindow"
Title="MainWindow" Height="350" Width="525" Icon="media/favicon.gif" Background="#FF3C3636" Foreground="{x:Null}">
<Window.Resources>
<Storyboard x:Key="logolayer2excompsoundfad_mp4"/>
</Window.Resources>
<Window.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FF6F6D95" Offset="1"/>
</LinearGradientBrush>
</Window.BorderBrush>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource logolayer2excompsoundfad_mp4}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Rectangle x:Name="Menu" Fill="#755E5E83" HorizontalAlignment="Left" Height="273" Margin="35,23,0,0" Stroke="Black" VerticalAlignment="Top" Width="446" RadiusY="27.5" RadiusX="27.5"/>
<Button Content="Log In" HorizontalAlignment="Left" Height="80" Margin="162,200,0,0" Style="{DynamicResource OTonButtonStyle1}" VerticalAlignment="Top" Width="187" FontFamily="Impact" FontSize="26.667" Foreground="#FF1C045B" Click="logIn"/>
<TextBox x:Name="UsernameField" HorizontalAlignment="Left" Height="25" Margin="204,57,0,0" TextWrapping="Wrap" Text="[Username]" VerticalAlignment="Top" Width="193" Background="#BD251E1E" UseLayoutRounding="False" FontFamily="Copperplate Gothic Light" FontSize="16">
<TextBox.Foreground>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FF1E2E95" Offset="0.5"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</TextBox.Foreground>
</TextBox>
<TextBlock HorizontalAlignment="Left" Height="16" Margin="98,57,0,0" TextWrapping="Wrap" Text="Username:" VerticalAlignment="Top" Width="101" FontFamily="Copperplate Gothic Light" FontSize="16">
<TextBlock.Foreground>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF0A1D5F" Offset="0.374"/>
<GradientStop Color="#FF6E7FB9" Offset="1"/>
</LinearGradientBrush>
</TextBlock.Foreground>
</TextBlock>
<PasswordBox x:Name="UserPassField" HorizontalAlignment="Left" Height="25" Margin="204,99,0,0" VerticalAlignment="Top" Width="193" Background="#BD251E1E" UseLayoutRounding="False" FontFamily="Copperplate Gothic Light" FontSize="16">
<PasswordBox.Foreground>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FF1E2E95" Offset="0.5"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</PasswordBox.Foreground>
</PasswordBox>
<TextBlock HorizontalAlignment="Left" Height="16" Margin="98,99,0,0" TextWrapping="Wrap" Text="Password:" VerticalAlignment="Top" Width="101" FontFamily="Copperplate Gothic Light" FontSize="16">
<TextBlock.Foreground>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF0A1D5F" Offset="0.374"/>
<GradientStop Color="#FF6E7FB9" Offset="1"/>
</LinearGradientBrush>
</TextBlock.Foreground>
</TextBlock>
<Canvas ClipToBounds="True" Name="errorCanvas" Width="446" Height="17" Margin="36,152,35,151">
<Rectangle x:Name="errorMarquee" Fill="#FF0A0A0C" HorizontalAlignment="Left" Height="17" Stroke="#FF5B1D1D" VerticalAlignment="Top" Width="446" Canvas.Left="-1" Visibility="Hidden"/>
<TextBlock x:Name="errorText" HorizontalAlignment="Left" Height="16" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="690" FontFamily="Copperplate Gothic Bold" FontSize="16" Foreground="#FF7E0202" Visibility="Hidden"/>
</Canvas>
</Grid>
</Window>
Anyone have any suggestions, perhaps?
you can just use one flag to check this
private static flag = true;
private void logIn(object sender, RoutedEventArgs e)
{
if(flag){
flag=false;
string nameRecord = "";
string passRecord = "";
if (UsernameField.Text == "" || UserPassField.Password == "")
{
openErrorMarquee("Username and password required");
}
else
{
using (otongadgethubEntities logCheck = new otongadgethubEntities())
{
var userNullCheck = logCheck.users.FirstOrDefault(a => a.username == UsernameField.Text);
if (userNullCheck == null)
{
openErrorMarquee("Username does not exist");
}
if (userNullCheck != null)
{
nameRecord = userNullCheck.username;
}
if (nameRecord == UsernameField.Text)
{
passRecord = Encrypt.MD5(UserPassField.Password).ToLower();
if (passRecord == userNullCheck.password)
{
//Yay! User logged in!
}
else
{
openErrorMarquee("Password invalid");
}
}
}
}
}
else
{
openErrorMarquee("you pressed more one time");
}
}
You can use StopWatch to check fast clicks. In code example given below, try pressing button slow and fast.
Stopwatch w = new Stopwatch();
long milliseconds_prev = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (_checkFastClicks())
{
Debug.WriteLine("Fast click");
}
else
Debug.WriteLine("Slow click");
}
bool _checkFastClicks()
{
bool result = false;
if (!w.IsRunning)
{
w.Start();
}
if (w.IsRunning)
{
if (w.ElapsedMilliseconds - milliseconds_prev < 500)//imp
{
if (w.ElapsedMilliseconds > 0)
{
milliseconds_prev = w.ElapsedMilliseconds;
result = true;
}
else
result = false;
}
else
{
milliseconds_prev = 0;
w.Reset();
w.Stop();
result = false;
}
}
return result;
}
Related
I'm using a user control I found online to express processing.
What I'm trying to do is showing a window containing this user control until main thread finishes processing.
This is the user control code:
public partial class CircularProgressBar
{
#region Data
private readonly DispatcherTimer animationTimer;
#endregion
#region Constructor
public CircularProgressBar()
{
InitializeComponent();
animationTimer = new DispatcherTimer( DispatcherPriority.ContextIdle, Dispatcher);
animationTimer.Interval = new TimeSpan(0, 0, 0, 0, 75);
}
#endregion
#region Private Methods
private void Start()
{
Mouse.OverrideCursor = Cursors.Wait;
animationTimer.Tick += HandleAnimationTick;
animationTimer.Start();
}
private void Stop()
{
animationTimer.Stop();
Mouse.OverrideCursor = Cursors.Arrow;
animationTimer.Tick -= HandleAnimationTick;
}
private void HandleAnimationTick(object sender, EventArgs e)
{
SpinnerRotate.Angle = (SpinnerRotate.Angle + 36) % 360;
}
private void HandleLoaded(object sender, RoutedEventArgs e)
{
const double offset = Math.PI;
const double step = Math.PI * 2 / 10.0;
SetPosition(C0, offset, 0.0, step);
SetPosition(C1, offset, 1.0, step);
SetPosition(C2, offset, 2.0, step);
SetPosition(C3, offset, 3.0, step);
SetPosition(C4, offset, 4.0, step);
SetPosition(C5, offset, 5.0, step);
SetPosition(C6, offset, 6.0, step);
SetPosition(C7, offset, 7.0, step);
SetPosition(C8, offset, 8.0, step);
}
private void SetPosition(Ellipse ellipse, double offset, double posOffSet, double step)
{
ellipse.SetValue(Canvas.LeftProperty, 50.0 + Math.Sin(offset + posOffSet * step) * 50.0);
ellipse.SetValue(Canvas.TopProperty, 50 + Math.Cos(offset + posOffSet * step) * 50.0);
}
private void HandleUnloaded(object sender, RoutedEventArgs e)
{
Stop();
}
private void HandleVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
bool isVisible = (bool)e.NewValue;
if (isVisible)
Start();
else
Stop();
}
#endregion
}
XAML:
<UserControl Height="Auto" Width="Auto" Background="Transparent" IsVisibleChanged="HandleVisibleChanged">
<Grid x:Name="LayoutRoot" Background="Transparent" ToolTip="Searching...." HorizontalAlignment="Center" VerticalAlignment="Center">
<Canvas RenderTransformOrigin="0.5,0.5"
HorizontalAlignment="Center"
VerticalAlignment="Center" Width="120"
Height="120" Loaded="HandleLoaded"
Unloaded="HandleUnloaded" >
<Ellipse x:Name="C0" Width="20" Height="20" Canvas.Left="0" Canvas.Top="0" Stretch="Fill" Fill="Black" Opacity="1.0"/>
<Ellipse x:Name="C1" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.9"/>
<Ellipse x:Name="C2" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.8"/>
<Ellipse x:Name="C3" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.7"/>
<Ellipse x:Name="C4" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.6"/>
<Ellipse x:Name="C5" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.5"/>
<Ellipse x:Name="C6" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.4"/>
<Ellipse x:Name="C7" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.3"/>
<Ellipse x:Name="C8" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="Black" Opacity="0.2"/>
<Canvas.RenderTransform>
<RotateTransform x:Name="SpinnerRotate"
Angle="0" />
</Canvas.RenderTransform>
</Canvas>
</Grid>
</UserControl>
I'm using this user control in a window and calling this window when I start processing using:
private void ThreadStartingPoint()
{
Window.Show();
Window.Focus();
System.Windows.Threading.Dispatcher.Run();
}
This is blocking the execution of main thread, I do not know what wrong I have done as I'm new to this.
Dispatcher.Run is certainly blocking. You cannot call this method on the main thread without blocking.
If you want to create a new window on a dedicated thread for some reason, you could refer to #Reed Copsey's blog post:
Launching a WPF Window in a Separate Thread, Part 1: http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-a-separate-thread-part-1/
It explains how to do this properly:
// Create a thread
Thread newWindowThread = new Thread(new ThreadStart(() =>
{
// Create our context, and install it:
SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher));
Window1 tempWindow = new Window1();
tempWindow.Content = new CircularProgressBar();
// When the window closes, shut down the dispatcher
tempWindow.Closed += (s, e) =>
Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
tempWindow.Show();
// Start the Dispatcher Processing
System.Windows.Threading.Dispatcher.Run();
}));
// Set the apartment state
newWindowThread.SetApartmentState(ApartmentState.STA);
// Make the thread a background thread
newWindowThread.IsBackground = true;
// Start the thread
newWindowThread.Start();
I am trying to add a scroll viewer to stackpanels - "gradpaneldesc" , "undergrapaneldesc" and "certficatedesc" which are inside another parent stackpanel- "mainpanel" respectively, but I am unable to achieve this as its showing me scrollviewer perhaps but there is no actual scrollbar,not realizing where is the mistake. Any help will be highly appreciated.
XAML
<UserControl x:Class="ISTE.Views.CoursesView"XAML
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ISTE.Views"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="1300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="400"/>
<ColumnDefinition Width="400"/>
<ColumnDefinition Width="400"/>
</Grid.ColumnDefinitions>
<Image Source="/Images/degree.jpg"
Stretch="Fill"
Height="250"
Grid.ColumnSpan="3"/>
<StackPanel x:Name="mainpanel1" Grid.Column="0">
<Button x:Name="Graduate" IsDefault="True" Click="Graduate_Click" >
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FF235DF0" Offset="0"/>
<GradientStop Color="#FFE7EBF5" Offset="1"/>
<GradientStop Color="#FF9EB6F3" Offset="0.632"/>
</LinearGradientBrush>
</Button.Background> Graduate
</Button>
<StackPanel x:Name="gradpanel" Height="200px"></StackPanel>
<Border x:Name="myBorder2">
<ScrollViewer>
<StackPanel x:Name="gradpaneldesc" Height="200px"></StackPanel>
</ScrollViewer>
</Border>
</StackPanel>
<StackPanel x:Name="mainpanel2" Grid.Column="1">
<Button x:Name="UnderGraduate" IsDefault="True" Click="UnderGraduate_Click" >
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FF235DF0" Offset="0"/>
<GradientStop Color="#FFE7EBF5" Offset="1"/>
<GradientStop Color="#FF9EB6F3" Offset="0.632"/>
</LinearGradientBrush>
</Button.Background> Undergraduate</Button>
<StackPanel x:Name="undergradpanel" Height="200px"></StackPanel>
<Border x:Name="myBorder1">
<ScrollViewer>
<StackPanel x:Name="undergradpaneldesc" Height="200px"></StackPanel>
</ScrollViewer>
</Border>
</StackPanel>
<StackPanel Grid.Column="2">
<Button x:Name="Certifications" IsDefault="True" Click="Certifications_Click" >
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FF235DF0" Offset="0"/>
<GradientStop Color="#FFE7EBF5" Offset="1"/>
<GradientStop Color="#FF9EB6F3" Offset="0.632"/>
</LinearGradientBrush>
</Button.Background> Certifications</Button>
<StackPanel x:Name="certpanel" Height="200px"></StackPanel>
<Border x:Name="myBorder3">
<ScrollViewer>
<StackPanel x:Name="certificatedesc" Height="200px"></StackPanel>
</ScrollViewer>
</Border>
</StackPanel>
</Grid>
CS
using ISTE.Models;
using ISTE.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ISTE.Views
{
/// <summary>
/// Interaction logic for CoursesView.xaml
/// </summary>
public partial class CoursesView : UserControl
{
CoursesVM vm;
public CoursesView()
{
InitializeComponent();
vm = new CoursesVM();
this.DataContext = vm;
vm.GetData();
}
bool flag=false;
bool flag1=false;
private void UnderGraduate_Click(object sender1, RoutedEventArgs e1)
{
if (flag1 == false)
{
foreach (Undergraduate grad in vm.ItemData.undergraduate)
{
var textb = new Button();
undergradpanel.Children.Add(textb);
textb.Content = grad.degreeName;
textb.Click += new RoutedEventHandler(ugdegreeEventHandler);
Console.WriteLine("graddegrees \t" + grad.degreeName);
}
}
flag1 = true;
}
void ugdegreeEventHandler(object sender2, RoutedEventArgs e2)
{
// Console.WriteLine("hi select");
var b = sender2 as Button;
// var textb2 = new TextBlock();
// textb2.Text
myBorder1.Background = Brushes.SkyBlue;
myBorder1.BorderBrush = Brushes.Blue;
myBorder1.BorderThickness = new Thickness(2);
myBorder1.CornerRadius = new CornerRadius(8);
myBorder1.Padding = new Thickness(6);
var degreeselected = b.Content.ToString();
if (undergradpaneldesc.Children.Count < 1)
{
var textb2 = new TextBlock();
textb2.Name = "textblock";
undergradpaneldesc.Children.Add(textb2);
foreach (Undergraduate grad in vm.ItemData.undergraduate)
{
if (grad.degreeName == degreeselected)
{
textb2.TextDecorations = TextDecorations.Underline;
textb2.Text = grad.description+"\n\n";
textb2.TextWrapping = TextWrapping.Wrap;
return;
}
}
}
else
{
foreach (Undergraduate grad in vm.ItemData.undergraduate)
{
if (grad.degreeName == degreeselected)
{
foreach (TextBlock ch in undergradpaneldesc.Children)
{
ch.Text = "";
ch.TextDecorations = TextDecorations.Underline;
ch.Text = grad.description+"\n\n";
ch.TextWrapping = TextWrapping.Wrap;
return;
}
}
}
}
}
private void Graduate_Click(object sender, RoutedEventArgs e)
{
if (flag == false)
{
foreach (Graduate grad in vm.ItemData.graduate)
{
var textb = new Button();
gradpanel.Children.Add(textb);
textb.Content = grad.degreeName;
textb.IsDefault = true;
textb.Click += new RoutedEventHandler(degreeEventHandler);
Console.WriteLine("graddegrees \t" + grad.degreeName);
}
}
flag = true;
}
void degreeEventHandler(object sender, RoutedEventArgs e)
{
// Console.WriteLine("hi select");
var b = sender as Button;
// var textb2 = new TextBlock();
// textb2.Text
var degreeselected = b.Content.ToString();
myBorder2.Background = Brushes.SkyBlue;
myBorder2.BorderBrush = Brushes.Black;
myBorder2.BorderThickness = new Thickness(2);
myBorder2.CornerRadius = new CornerRadius(8);
myBorder2.Padding = new Thickness(6);
if (gradpaneldesc.Children.Count<1)
{
var textb1 = new TextBlock();
textb1.Name = "textblock1";
gradpaneldesc.Children.Add(textb1);
foreach (Graduate grad in vm.ItemData.graduate)
{
if (grad.degreeName == degreeselected)
{
if (grad.degreeName != "graduate advanced certificates")
{
textb1.Text = grad.description;
textb1.TextDecorations = TextDecorations.Underline;
foreach (var conc in grad.concentrations)
{
textb1.Text += conc + "\n\n";
}
textb1.TextWrapping = TextWrapping.Wrap;
return;
}
else
{
textb1.TextDecorations = TextDecorations.Underline;
foreach (var conc in grad.availableCertificates)
{
textb1.Text += conc + "\n\n";
}
textb1.TextWrapping = TextWrapping.Wrap;
return;
}
}
}
}
else
{
foreach (Graduate grad in vm.ItemData.graduate)
{
if (grad.degreeName == degreeselected)
{
if (grad.degreeName != "graduate advanced certificates")
{
foreach (TextBlock ch in gradpaneldesc.Children)
{
ch.Text = "";
ch.Text = grad.description + "\n\n";
ch.TextDecorations = TextDecorations.Underline;
foreach (var conc in grad.concentrations)
{
ch.Text += conc + "\n";
}
ch.TextWrapping = TextWrapping.Wrap;
return;
}
}
else
{
foreach (TextBlock ch in gradpaneldesc.Children)
{
ch.Text = "";
ch.TextDecorations = TextDecorations.Underline;
foreach (var conc in grad.availableCertificates)
{
ch.Text += conc + "\n";
}
ch.TextWrapping = TextWrapping.Wrap;
return;
}
}
}
}
}
}
private void Certifications_Click(object sender, RoutedEventArgs e)
{
var textb3 = new TextBlock();
textb3.Name = "textblock3";
certificatedesc.Children.Add(textb3);
textb3.TextDecorations = TextDecorations.Underline;
myBorder3.Background = Brushes.SkyBlue;
myBorder3.BorderBrush = Brushes.Black;
myBorder3.BorderThickness = new Thickness(2);
myBorder3.CornerRadius = new CornerRadius(8);
myBorder3.Padding = new Thickness(6);
foreach (Graduate grad in vm.ItemData.graduate)
{
if (grad.degreeName == "graduate advanced certificates")
{
textb3.Text = grad.description;
textb3.TextDecorations = TextDecorations.Underline;
foreach (var conc in grad.availableCertificates)
{
textb3.Text += conc + "\n\n";
}
textb3.TextWrapping = TextWrapping.Wrap;
return;
}
}
}
}
}
You need to specify the height of the ScrollViewer not the StackPanel, because otherwise the StackPanel won't extend beyond the bounds of the ScrollViewer and the scroll bar won't display.
<Border x:Name="myBorder2">
<ScrollViewer Height="200px">
<StackPanel x:Name="gradpaneldesc">
</StackPanel>
</ScrollViewer>
</Border>
I have next structure:
Main window
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid Margin="100 70 0 0">
<local:RotateControl x:Name="rtc1" Panel.ZIndex="1"
Width="{Binding ElementName=window, Path=ActualHeight, Converter={StaticResource SizeConverter}}"
Height="{Binding ElementName=window, Path=ActualHeight, Converter={StaticResource SizeConverter}}"
Radius="{Binding ElementName=window, Path=ActualHeight, Converter={StaticResource RadiusConverter}}"
Loaded="rtc1_Loaded" SizeChanged="rtc1_SizeChanged"/>
</Grid>
<StackPanel HorizontalAlignment="Right" Canvas.Right="80" Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBox x:Name="year" Width="40"></TextBox>
<TextBox x:Name="month" Width="20"></TextBox>
<TextBox x:Name="day" Width="20"></TextBox>
<TextBox x:Name="hour" Width="20"></TextBox>
<TextBox x:Name="min" Width="20"></TextBox>
<TextBox x:Name="sec" Width="20"></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBox x:Name="lat" Width="80" Text="55.75"></TextBox>
<TextBox x:Name="lng" Width="80" Text="37.583333"></TextBox>
</StackPanel>
<ComboBox x:Name="cbHSys" Width="300" SelectedIndex="0"></ComboBox>
<Button x:Name="GatData" Click="GatData_Click">Get data</Button>
<ScrollViewer>
<Label x:Name="julday"></Label>
</ScrollViewer>
</StackPanel>
</Canvas>
Custom control
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Astro"
xmlns:s="clr-namespace:System;assembly=mscorlib">
<local:XLineCoordConverter x:Key="XLineCoordConverter" />
<local:YLineCoordConverter x:Key="YLineCoordConverter" />
<SolidColorBrush x:Key="Blue1Brush" Color="#e2edfa" />
<SolidColorBrush x:Key="Blue2Brush" Color="#0080c0" />
<Pen x:Key="BlackPen1" Thickness="1" Brush="Black"></Pen>
<Pen x:Key="BluePen1" Thickness="0.1" Brush="{StaticResource Blue2Brush}"></Pen>
<Style TargetType="{x:Type local:RotateControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:RotateControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid Background="Transparent">
<Line X1="{Binding Path=Radius}" Y1="{Binding Path=Radius}" Stroke="White" StrokeThickness="1">
<Line.X2>
<MultiBinding Converter="{StaticResource XLineCoordConverter}" ConverterParameter="1">
<Binding Path="Radius"/>
<Binding Path="House1"/>
<Binding Path="House2"/>
</MultiBinding>
</Line.X2>
<Line.Y2>
<MultiBinding Converter="{StaticResource YLineCoordConverter}" ConverterParameter="1">
<Binding Path="Radius"/>
<Binding Path="House1"/>
<Binding Path="House2"/>
</MultiBinding>
</Line.Y2>
</Line>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
And model:
public class CircleModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
double _radius;
public double Radius
{
get
{
return _radius;
}
set
{
if (_radius == value) return;
_radius = value;
OnPropertyChanged("Radius");
}
}
double _angel;
public double Angel
{
get
{
return _angel;
}
set
{
if (_angel == value) return;
_angel = value;
OnPropertyChanged("Angel");
}
}
double _house1;
public double House1
{
get
{
return _house1;
}
set
{
if (_house1 == value) return;
_house1 = value;
OnPropertyChanged("House1");
}
}
...................
}
And code for change data:
private void GetData()
{
julday.Content = "";
//SetCurDate();
DateTime date = new DateTime(Convert.ToInt32(year.Text), Convert.ToInt32(month.Text), Convert.ToInt32(day.Text),
Convert.ToInt32(hour.Text), Convert.ToInt32(min.Text), Convert.ToInt32(sec.Text));
CalcNatalChart(date);
_model.Radius = (this.ActualHeight - (this.ActualHeight > 150 ? 150 : 0)) / 2;
this.ViewModel = _model;
}
private void GatData_Click(object sender, RoutedEventArgs e)
{
GetData();
}
private void rtc1_Loaded(object sender, RoutedEventArgs e)
{
GetData();
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromSeconds(1.0);
_timer.Tick += timer_Tick;
_timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
julday.Content = "";
CalcNatalChart(DateTime.Now);
_model.Radius = (this.ActualHeight - (this.ActualHeight > 150 ? 150 : 0)) / 2;
this.ViewModel = _model;
}
All data in the form of updated correctly but View not. Only if press button GatData_Click. Dynamically change the data does not work.
Can you help me to solve it problem? Thanks
The problem is in these lines:
_model.Radius = (this.ActualHeight - (this.ActualHeight > 150 ? 150 : 0)) / 2;
this.ViewModel = _model;
After you reassign ViewModel, the view doesn't know about this change and uses old object instance. Either initialize ViewModel only once in constructor and then change it's properties or make that ViewModel property also observable so that you could notify when the data is changed.
Try this one...
instead of your this.ViewModel = _model; put this.ViewModel.Radious = _model.Radious;
Is there a way in WPF where I can remove the main window's border, yet allow that window to be resized (without grip)?
I realized there's a way to do this scenario by setting resize mode to CanResizeWithGrip. However, I want to be able to do it with the resize mode set to CanResize.
I tried setting the following:
ResizeMode="CanResize"
WindowStyle="None"
AllowsTransparency="True"
However, by setting AllowsTransparency, it removes the ability to resize without the grip. Any ideas how I can pull this off?
I also should note that I can't set AllowsTransparency to true anyway, because I am using a winformshost control in my window, which is not shown when AllowsTransparency is true.
I know this is an old question, but I just wanted to put up a working sample for newcomers.
Xaml Window:
<Window x:Class="CustomWindowDemo.DemoCustomWindow"
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:CustomWindowDemo"
mc:Ignorable="d"
Title="DemoCustomWindow" Height="300" Width="300" Background="{x:Null}" AllowsTransparency="True" WindowStyle="None">
<Window.Resources>
<Style x:Key="BorderThumb" TargetType="Thumb">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Rectangle MinWidth="4" MinHeight="4" StrokeThickness="0">
<Rectangle.Fill>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.HighlightColorKey}}" Opacity="0.05"/>
</Rectangle.Fill>
</Rectangle>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Border BorderBrush="#55FFFFFF" BorderThickness="1" CornerRadius="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border MouseMove="Header_MouseMove" DockPanel.Dock="Top" Height="32" Grid.Row="1" Grid.Column="1">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,3">
<GradientStop Color="#3BB2EA" Offset="0" />
<GradientStop Color="#EFF7FA" Offset="0.3" />
</LinearGradientBrush>
</Border.Background>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" Text="{Binding Path=Title, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
<Button x:Name="btn_Minimize" Background="{x:Null}" BorderBrush="{x:Null}" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" BorderThickness="0" Click="btn_Minimize_Click" Grid.Column="1">
<Image Source="Resources/Ahmadhania-Spherical-Minimize.ico"/>
</Button>
<Button x:Name="btn_Maximize" Background="{x:Null}" BorderBrush="{x:Null}" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" BorderThickness="0" Grid.Column="2" Click="btn_Maximize_Click">
<Image Source="Resources/1412181205_61002.ico"/>
</Button>
<Button x:Name="btn_Close" Background="{x:Null}" BorderBrush="{x:Null}" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" BorderThickness="0" Grid.Column="3" Click="btn_Close_Click">
<Image Source="Resources/Ahmadhania-Spherical-Close(1).ico"/>
</Button>
</Grid>
</Border>
<Thumb x:Name="ThumbBottom" DragDelta="ThumbBottom_DragDelta" HorizontalAlignment="Stretch" Cursor="SizeNS" Grid.Column="0" Background="{x:Null}" Margin="3,0" Grid.ColumnSpan="3" Grid.Row="3" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}"/>
<Thumb x:Name="ThumbTop" DragDelta="ThumbTop_DragDelta" HorizontalAlignment="Stretch" Cursor="SizeNS" Grid.Column="0" Background="{x:Null}" Margin="3,0" Grid.ColumnSpan="3" Height="4" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}"/>
<Thumb x:Name="ThumbBottomRightCorner" DragDelta="ThumbBottomRightCorner_DragDelta" HorizontalAlignment="Right" Cursor="SizeNWSE" Grid.Row="3" Grid.Column="3" Background="{x:Null}" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}"/>
<Thumb x:Name="ThumbTopRightCorner" DragDelta="ThumbTopRightCorner_DragDelta" HorizontalAlignment="Right" Cursor="SizeNESW" Grid.Row="0" Grid.Column="2" Background="{x:Null}" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}"/>
<Thumb x:Name="ThumbTopLeftCorner" DragDelta="ThumbTopLeftCorner_DragDelta" HorizontalAlignment="Left" Cursor="SizeNWSE" Grid.Row="0" Grid.Column="0" Background="{x:Null}" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}" />
<Thumb x:Name="ThumbBottomLeftCorner" DragDelta="ThumbBottomLeftCorner_DragDelta" HorizontalAlignment="Left" Cursor="SizeNESW" Grid.Row="3" Grid.Column="0" Background="{x:Null}" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}" />
<Thumb x:Name="ThumbRight" DragDelta="ThumbRight_DragDelta" Cursor="SizeWE" Grid.Column="2" Grid.RowSpan="4" Background="{x:Null}" Margin="0,3" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}"/>
<Thumb x:Name="ThumbLeft" DragDelta="ThumbLeft_DragDelta" Cursor="SizeWE" Grid.Column="0" Grid.RowSpan="4" HorizontalContentAlignment="Right" Background="{x:Null}" Margin="0,3" Style="{Binding Mode=OneWay, Source={StaticResource BorderThumb}}"/>
<Grid x:Name="Grid_Content" Background="#EFF7FA" Grid.Row="2" Grid.Column="1">
</Grid>
</Grid>
</Border>
</Window>
C# code behind:
using System.Windows.Interop;
using winforms = System.Windows.Forms;
namespace CustomWindowDemo
{
/// <summary>
/// Interaction logic for DemoCustomWindow.xaml
/// </summary>
public partial class DemoCustomWindow : Window
{
bool Maximized = false;
int NormalWidth = 0;
int NormalHeight = 0;
int NormalX = 0;
int NormalY = 0;
public DemoCustomWindow()
{
InitializeComponent();
}
#region Header & Resize
void Header_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
this.DragMove();
}
void ThumbBottomRightCorner_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Width + e.HorizontalChange > 10)
this.Width += e.HorizontalChange;
if (this.Height + e.VerticalChange > 10)
this.Height += e.VerticalChange;
}
void ThumbTopRightCorner_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Width + e.HorizontalChange > 10)
this.Width += e.HorizontalChange;
if (this.Top + e.VerticalChange > 10)
{
this.Top += e.VerticalChange;
this.Height -= e.VerticalChange;
}
}
void ThumbTopLeftCorner_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Left + e.HorizontalChange > 10)
{
this.Left += e.HorizontalChange;
this.Width -= e.HorizontalChange;
}
if (this.Top + e.VerticalChange > 10)
{
this.Top += e.VerticalChange;
this.Height -= e.VerticalChange;
}
}
void ThumbBottomLeftCorner_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Left + e.HorizontalChange > 10)
{
this.Left += e.HorizontalChange;
this.Width -= e.HorizontalChange;
}
if (this.Height + e.VerticalChange > 10)
this.Height += e.VerticalChange;
}
void ThumbRight_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Width + e.HorizontalChange > 10)
this.Width += e.HorizontalChange;
}
void ThumbLeft_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Left + e.HorizontalChange > 10)
{
this.Left += e.HorizontalChange;
this.Width -= e.HorizontalChange;
}
}
void ThumbBottom_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Height + e.VerticalChange > 10)
this.Height += e.VerticalChange;
}
void ThumbTop_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
if (this.Top + e.VerticalChange > 10)
{
this.Top += e.VerticalChange;
this.Height -= e.VerticalChange;
}
}
void btn_Minimize_Click(object sender, RoutedEventArgs e)
{
WindowState = WindowState.Minimized;
}
void btn_Maximize_Click(object sender, RoutedEventArgs e)
{
if (Maximized == true)
{
this.Width = NormalWidth;
this.Height = NormalHeight;
this.Left = NormalX;
this.Top = NormalY;
Maximized = false;
Thumbs();
}
else
{
NormalX = (int)this.Left;
NormalY = (int)this.Top;
NormalHeight = (int)this.Height;
NormalWidth = (int)this.Width;
this.Left = winforms.Screen.FromHandle(new WindowInteropHelper(this).Handle).WorkingArea.Left;
this.Top = winforms.Screen.FromHandle(new WindowInteropHelper(this).Handle).WorkingArea.Top;
this.Width = winforms.Screen.FromHandle(new WindowInteropHelper(this).Handle).WorkingArea.Width;
this.Height = winforms.Screen.FromHandle(new WindowInteropHelper(this).Handle).WorkingArea.Height;
Maximized = true;
Thumbs();
}
}
void btn_Close_Click(object sender, RoutedEventArgs e)
{
Close();
}
void Thumbs()
{
if (Maximized == true)
{
ThumbBottom.Visibility = Visibility.Collapsed;
ThumbLeft.Visibility = Visibility.Collapsed;
ThumbTop.Visibility = Visibility.Collapsed;
ThumbRight.Visibility = Visibility.Collapsed;
ThumbTopLeftCorner.Visibility = Visibility.Collapsed;
ThumbTopRightCorner.Visibility = Visibility.Collapsed;
ThumbBottomLeftCorner.Visibility = Visibility.Collapsed;
ThumbBottomRightCorner.Visibility = Visibility.Collapsed;
}
else
{
ThumbBottom.Visibility = Visibility.Visible;
ThumbLeft.Visibility = Visibility.Visible;
ThumbTop.Visibility = Visibility.Visible;
ThumbRight.Visibility = Visibility.Visible;
ThumbTopLeftCorner.Visibility = Visibility.Visible;
ThumbTopRightCorner.Visibility = Visibility.Visible;
ThumbBottomLeftCorner.Visibility = Visibility.Visible;
ThumbBottomRightCorner.Visibility = Visibility.Visible;
}
}
#endregion
}
}
This can happen if ResizeBorderThickness is set to 0.
It can be set to a positive value in XAML like this:
<WindowChrome>
<WindowChrome.ResizeBorderThickness>
<Thickness>1</Thickness>
</WindowChrome.ResizeBorderThickness>
</WindowChrome>
You can use the WPF customizable window library, available here: http://wpfwindow.codeplex.com/
Then, when using the library's window type, you can set the same properties as you listed above
<CustomWindow:EssentialWindow x:Class="CustomWindowDemo.DemoEssentialWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:CustomWindow="clr-namespace:CustomWindow;assembly=CustomWindow"
AllowsTransparency="True" ResizeMode="CanResize" WindowStyle="None" Title="EssentialWindow"
Height="300" Width="250">
The user needs something to interact with to resize the window. If you don't like the default border or grip, you'll need to add some other control with a click and drag behavior that resizes the window. Perhaps a line on each edge of the window?
The simplest, but maybe too simple is
this.MouseLeftButtonDown += delegate { this.DragMove(); };
I am developing an application based on OptiTrack SDK (from NaturalPoint). I need to run the application window as "Always on Top". The window is designed in XAML and is controled in the class "CameraView" but it does not seem to include a "TopMost" property or equivalent. Attached are the code of "CameraView.xaml.cs" and the code of "CameraView.xaml" that are part of OptiTrack SDK (NaturalPoint) called "Single_Camera_CSharp_.NET_3.0".
One could expect the class CameraView to contain properties or members to set the position of the window on the screen or to set it to TopMost but as far as searched I found nothing. I wonder what I should do.
Thank you,
Brian
================
"CameraView.xaml.cs"
using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Windows.Threading;
namespace TestProject
{
public partial class CameraView
{
private const int NP_OPTION_OBJECT_COLOR_OPTION = 3;
private const int NP_OPTION_VIDEO_TYPE = 48;
private const int NP_OPTION_NUMERIC_DISPLAY_ON = 71;
private const int NP_OPTION_NUMERIC_DISPLAY_OFF = 72;
private const int NP_OPTION_FETCH_RLE = 73;
private const int NP_OPTION_FETCH_GRAYSCALE = 74;
private const int NP_OPTION_FRAME_DECIMATION = 52;
private const int NP_OPTION_INTENSITY = 50;
private const int NP_OPTION_SEND_EMPTY_FRAMES = 41;
private const int NP_OPTION_THRESHOLD = 5;
private const int NP_OPTION_EXPOSURE = 46;
private const int NP_OPTION_SEND_FRAME_MASK = 73;
private const int NP_OPTION_TEXT_OVERLAY_OPTION = 74;
// public delegate void OnCameraViewCreate(CameraView camera);
// public static OnCameraViewCreate onCameraViewCreate;
private System.Drawing.Bitmap raw = new System.Drawing.Bitmap(353, 288, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
private int mFrameCounter;
private int mDisplayCounter;
private DispatcherTimer timer1 = new DispatcherTimer();
private bool mVideoFrameAvailable = false;
private int mNumeric = -1;
private bool mGreyscale = false;
private bool mOverlay = true;
public CameraView()
{
this.InitializeComponent();
timer1.Interval = new TimeSpan(0, 0, 0, 0, 10);
timer1.Tick += new EventHandler(timer1_Tick);
}
public int Numeric
{
get { return mNumeric; }
set
{
mNumeric = value % 100;
if (mNumeric >= 0)
{
if (Camera != null)
Camera.SetOption(NP_OPTION_NUMERIC_DISPLAY_ON, value % 100);
}
}
}
private bool CameraRunning = false;
private OptiTrack.NPCamera mCamera;
public OptiTrack.NPCamera Camera
{
get { return mCamera; }
set
{
if (mCamera == value) return; //== Don't do anything if you're assigning the same camera ==
if (mCamera != null)
{
//== Shut the selected camera down ==<<
if (CameraRunning)
{
CameraRunning = false;
mCamera.Stop();
mCamera.FrameAvailable -= FrameAvailable;
}
}
mCamera = value;
if (mCamera == null)
{
mNumeric = -1;
}
else
{
serialLabel.Content = "Camera "+mCamera.SerialNumber.ToString(); //mNumeric.ToString();
}
}
}
private void FrameAvailable(OptiTrack.NPCamera Camera)
{
mFrameCounter++;
try
{
OptiTrack.NPCameraFrame frame = Camera.GetFrame(0);
int id = frame.Id;
if (CameraRunning)
{
GetFrameData(Camera, frame);
}
frame.Free();
}
catch (Exception)
{
int r = 0;
r++;
}
}
private void GetFrameData(OptiTrack.NPCamera camera, OptiTrack.NPCameraFrame frame)
{
BitmapData bmData = raw.LockBits(new System.Drawing.Rectangle(0, 0, raw.Width, raw.Height),
ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
int stride = bmData.Stride;
System.IntPtr bufferPtr = bmData.Scan0;
unsafe
{
byte* buffer = (byte*)(void*)bufferPtr;
camera.GetFrameImage(frame, bmData.Width, bmData.Height, bmData.Stride, 32, ref buffer[0]);
}
raw.UnlockBits(bmData);
mVideoFrameAvailable = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
if (CameraRunning && mVideoFrameAvailable)
{
mVideoFrameAvailable = false;
cameraImage.Source = Img(raw);
mDisplayCounter++;
}
}
private System.Windows.Media.ImageSource Img(System.Drawing.Bitmap img)
{
System.Drawing.Imaging.BitmapData bmData = img.LockBits(new System.Drawing.Rectangle(0, 0, img.Width, img.Height),
System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
System.Windows.Media.Imaging.BitmapSource bitmap = System.Windows.Media.Imaging.BitmapSource.Create(
img.Width, img.Height, 96, 96, PixelFormats.Bgra32,
System.Windows.Media.Imaging.BitmapPalettes.WebPalette,
bmData.Scan0, bmData.Stride * bmData.Height, bmData.Stride);
img.UnlockBits(bmData);
return bitmap;
}
private void startStopButton_Click(object sender, RoutedEventArgs e)
{
if (CameraRunning)
StopCamera();
else
StartCamera();
}
public void StartCamera()
{
if (Camera != null)
{
mFrameCounter = 0;
mDisplayCounter = 0;
Camera.FrameAvailable += FrameAvailable;
Camera.SetOption(NP_OPTION_VIDEO_TYPE, 0);
Camera.SetOption(NP_OPTION_FRAME_DECIMATION, 1);
Camera.SetOption(NP_OPTION_INTENSITY, 0);
Camera.SetOption(NP_OPTION_EXPOSURE, 10);
Camera.SetOption(NP_OPTION_THRESHOLD, 50);
Camera.SetOption(NP_OPTION_OBJECT_COLOR_OPTION, 0);
SetOverlayOption();
SetGreyscaleOption();
timer1.Start();
Camera.Start();
CameraRunning = true;
this.Numeric = mNumeric;
startStopButton.Content = "Stop Camera";
}
}
private void SetGreyscaleOption()
{
if(mGreyscale)
Camera.SetOption(NP_OPTION_VIDEO_TYPE, 1);
else
Camera.SetOption(NP_OPTION_VIDEO_TYPE, 0);
}
private void SetOverlayOption()
{
if(mOverlay)
Camera.SetOption(NP_OPTION_TEXT_OVERLAY_OPTION, 255);
else
Camera.SetOption(NP_OPTION_TEXT_OVERLAY_OPTION, 0);
}
public void StopCamera()
{
if (Camera != null)
{
Camera.Stop();
timer1.Stop();
CameraRunning = false;
Camera.FrameAvailable -= FrameAvailable;
Camera.SetOption(NP_OPTION_NUMERIC_DISPLAY_OFF, 0);
startStopButton.Content = "Start Camera";
}
}
private void greyscaleButton_Click(object sender, RoutedEventArgs e)
{
if(mGreyscale)
mGreyscale = false;
else
mGreyscale = true;
SetGreyscaleOption();
}
private void OverlayButton_Click(object sender, RoutedEventArgs e)
{
if(mOverlay)
mOverlay = false;
else
mOverlay = true;
SetOverlayOption();
}
private void exposureSlider_ValueChanged(object sender, RoutedEventArgs e)
{
if (mCamera!=null)
{
mCamera.SetOption(NP_OPTION_EXPOSURE, (int) this.exposureSlider.Value);
}
}
private void thresholdSlider_ValueChanged(object sender, RoutedEventArgs e)
{
if (mCamera != null)
{
mCamera.SetOption(NP_OPTION_THRESHOLD, (int)this.thresholdSlider.Value);
}
}
private void optionsButton_Click(object sender, RoutedEventArgs e)
{
if (!propertyPanel.IsVisible)
propertyPanel.Visibility = Visibility.Visible;
else
propertyPanel.Visibility = Visibility.Collapsed;
}
}
}
================
"CameraView.xaml"
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="TestProject.CameraView"
x:Name="CameraView1"
Width="Auto" Height="Auto"
xmlns:d="http://schemas.microsoft.com/expression/blend/2006"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
>
<Grid x:Name="LayoutRoot" Width="Auto" Height="Auto">
<Grid.Background>
<x:Null/>
</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="113.904"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="26.667"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Margin="0,0,0,0" Grid.ColumnSpan="2">
<Rectangle RadiusX="1.25" RadiusY="1.25" Margin="0,0,0,0" VerticalAlignment="Stretch">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.492,0.149" StartPoint="0.492,0.843">
<GradientStop Color="#FF000000" Offset="0"/>
<GradientStop Color="#FF23283F" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
<Rectangle.Stroke>
<LinearGradientBrush EndPoint="0.291,-4.231" StartPoint="1.668,18.025">
<GradientStop Color="#FF000000" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Stroke>
</Rectangle>
<Rectangle RadiusX="3.333" RadiusY="3.333" Opacity="0.13" Margin="0,0,0,13">
<Rectangle.Fill>
<SolidColorBrush Color="#FFFFFFFF"/>
</Rectangle.Fill>
<Rectangle.Stroke>
<x:Null/>
</Rectangle.Stroke>
</Rectangle>
</Grid>
<Image Margin="0,0,0,0" x:Name="cameraImage" Grid.ColumnSpan="2" Grid.Row="1"/>
<Label x:Name="serialLabel" FontSize="10" FontWeight="Bold" Foreground="#FFDEDADA" Content="Camera 10024" HorizontalAlignment="Right" Margin="0,0,4,0" VerticalAlignment="Top" Grid.Column="1">
<Label.BitmapEffect>
<OuterGlowBitmapEffect GlowColor="#FF000000" GlowSize="4" Opacity="0.7"/>
</Label.BitmapEffect>
</Label>
<WrapPanel Margin="3,3,3,3">
<Button HorizontalAlignment="Stretch" Margin="0,0,0,0" x:Name="startStopButton" Width="100" Height="Auto" BorderThickness="0,0,0,0" Content="Start Camera" Click="startStopButton_Click"/>
<Button x:Name="optionsButton" Width="61.474" Height="Auto" BorderThickness="0,0,0,0" Content="Options" Click="optionsButton_Click"/>
</WrapPanel>
<Grid Visibility="Visible" d:LayoutOverrides="HorizontalAlignment, VerticalAlignment" HorizontalAlignment="Right" Margin="0,0,16,16" x:Name="propertyPanel" VerticalAlignment="Bottom" Width="169.237" Height="81.455" Grid.ColumnSpan="2" Grid.Row="1">
<Rectangle Stroke="#FFFFFFFF" StrokeThickness="3" Margin="0,0,0,0">
<Rectangle.BitmapEffect>
<DropShadowBitmapEffect/>
</Rectangle.BitmapEffect>
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FF1E212F" Offset="0"/>
<GradientStop Color="#FF313551" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Slider HorizontalAlignment="Stretch" Margin="62.633,5,4.681,0" x:Name="exposureSlider" VerticalAlignment="Top" Width="Auto" Height="Auto" Orientation="Horizontal" Maximum="255" ValueChanged="exposureSlider_ValueChanged"/>
<Label x:Name="serialLabel_Copy" FontSize="10" FontWeight="Bold" Foreground="#FFDEDADA" Content="Exposure" HorizontalAlignment="Left" Margin="3.853,3.853,0,0" VerticalAlignment="Top" Width="57.352">
<Label.BitmapEffect>
<OuterGlowBitmapEffect GlowColor="#FF000000" GlowSize="4" Opacity="0.7"/>
</Label.BitmapEffect>
</Label>
<Label x:Name="serialLabel_Copy1" FontSize="10" FontWeight="Bold" Foreground="#FFDEDADA" Content="Threshold" d:LayoutOverrides="Height" HorizontalAlignment="Left" Margin="3.853,27.691,0,0" VerticalAlignment="Top" Width="59.829">
<Label.BitmapEffect>
<OuterGlowBitmapEffect GlowColor="#FF000000" GlowSize="4" Opacity="0.7"/>
</Label.BitmapEffect>
</Label>
<Slider x:Name="thresholdSlider" Width="Auto" Orientation="Horizontal" Maximum="253" d:LayoutOverrides="Height, Margin" Margin="62.633,27.691,4.681,0" VerticalAlignment="Top" Minimum="54" Value="54" ValueChanged="thresholdSlider_ValueChanged"/>
<Button x:Name="greyScaleButton" Width="75.333" Content="Greyscale" Click="greyscaleButton_Click" HorizontalAlignment="Left" Height="21" d:LayoutOverrides="Height" Margin="8,53.761,0,0" VerticalAlignment="Top"/>
<Button x:Name="Overlay" Height="21" Content="Overlay" Click="OverlayButton_Click" d:LayoutOverrides="Height" HorizontalAlignment="Right" Margin="0,53.761,8,0" VerticalAlignment="Top" Width="64"/>
</Grid>
</Grid>
</UserControl>
The Topmost property exists on the Window class: http://msdn.microsoft.com/en-us/library/system.windows.window.topmost.aspx.
Your CameraView class is derived from UserControl, which is a kind of control that sits inside a Window (or other container such as a Page, but that's not important here). UserControl doesn't have a Topmost property because it doesn't appear independently on the desktop.
Host your CameraView in a Window and set the Window.Topmost:
<!-- MyWindow.xaml -->
<Window ...
xmlns:local="clr-namespace:TestProject"
Topmost="True">
<local:CameraView />
</Window>
where the ellipses represent the default gunk like x:Class and WPF xmlns declarations that Visual Studio creates for you.
In the UserControl code behind, you can get a reference to the window that is hosting it, then set the Topmost property. Example,
Window parent = Window.GetWindow(this);
parent.Topmost = true;
This is UserControl. You can set TopMost property for Windows only