Cancel button writes to text box - c#

I have a wpf application that prompts a user to enter some a numeric input for how many seconds to set stale time from a main window. The value is defaulted at 120, if the user wishes to change it he would click on the button and the a new instance of the window would come up and prompt the user to change it, I have the number validation part working, however if the user clicks the cancel button the current value is replaced by a blank(""), empty space, because that is technically the value in enter time window text box. How would I stop this from happening? I just want the window to close the current value to stay what it is. NOTE this also happens if the user enters, say 3, into the box, the default value is replaced with 3 even though the user hit cancel.
Here is the WPF:
<Window x:Class="WpfClient.StaleTimeDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Stale Time" FontFamily="Arial" Width="450" Height="300" Topmost="True" WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Label Margin="10" FontSize="16">Enter new Stale Time</Label>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0, 10, 10, 0">
<TextBox Name="StaleTime" FontSize="20" Width="150" HorizontalAlignment="Left" VerticalContentAlignment="Center" Text="" AcceptsReturn="False" DataContext="{Binding}" PreviewTextInput="StaleTime_PreviewTextInput"></TextBox>
<Label Width="Auto" FontSize="20" Height="Auto" VerticalContentAlignment="Center">Seconds</Label>
</StackPanel>
<StackPanel Grid.Row="3" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
<Button Name="SaveButton" Margin="10,10,10,10" Style="{StaticResource controlButtonStyle}" IsDefault="True" Click="SaveButton_Click">Save</Button>
<Button Name="CancelButton" Margin="10,10,10,10" Style="{StaticResource controlButtonStyle}" IsCancel="True" Click="CancelButton_Click">Cancel</Button>
</StackPanel>
</Grid>
Here is the C#:
public partial class StaleTimeDialog : Window
{
private Client client = null;
private SystemStatus systemStatus = null;
private UserTypes userType = UserTypes.Unknown;
private bool isStandaloneGUI = false;
private static string CurrentValue = "";
public StaleTimeDialog()
{
InitializeComponent();
CurrentValue = StaleTime.Text;
}
private void Cancel_Click(object sender, EventArgs e)
{
StaleTime.Text = CurrentValue.ToString();
CancelButton.IsCancel = true;
this.Close();
}
private void StaleTime_KeyPress(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
e.Handled = true;
}
}
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
if (true)
{
this.Close();
}
else
{
ErrorDialog errorDialog = new ErrorDialog(DialogType.OKDialog, IconType.Warning, "Save failed");
errorDialog.ShowDialog();
}
}
private void StaleTime_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
CheckIsNumeric(e);
}
private void CheckIsNumeric(TextCompositionEventArgs e)
{
int result;
if (!(int.TryParse(e.Text, out result) || e.Text == "."))
{
e.Handled = true;
}
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
StaleTime.Undo();
}
}
This is the instance where it is called in C#:
private void EditParametersButton_Click(object sender, RoutedEventArgs e)
{
StaleTimeDialog staletimeDialog = new StaleTimeDialog();
bool? result = staletimeDialog.ShowDialog();
if (staletimeDialog.StaleTime.Text.Equals("") || staletimeDialog.StaleTime.Text.Equals(" "))
{
App.ChipStale = DefaultStaleTime;
}
else
{
App.ChipStale = Convert.ToInt32(staletimeDialog.StaleTime.Text);
}
FoodParametersLine4Run.Text = App.ChipStale.ToString();
}

You need to bind that TextBox Text property in TwoWay mode to a public property supporting change notification in the DataContext of that View (typically a ViewModel) and set the UpdateSourceTrigger to LostFocus or Explicit.
Once you do that all your problems will disappear and as a bonus you'll get rid of all that ugly code-behind... that's the WPF way of doing things.

Related

WPF Need to find a way to identify TypeOf on custom Page class

I have a Window class called MainWindow, and in its constructor, builds a default Page class I call, MonitorPage that populates my window with this page at launch. In my MainWindow, I have three buttons that act as page tabs or menu buttons that upon clicking them will create an instance of a different Page class, in my case I have three unique pages. MonitorPage, DataBasePage, HelpPage. In my MainWindow, I want to "grey-out" the tab button when that corresponding page is up. I have a method in MainWindow called, PageState(), that tries to identify which page is currently up to enable or disable and grey out the tabs. My problem is that I get a NullReferenceException in my method at the first IF check.
The Error I'm Getting:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
System.Windows.Controls.ContentControl.Content.get returned null.
C#:
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Media;
namespace EyeInTheSky
{
/// <summary>
/// Interaction logic for MainWindow.xaml + backend code for FileSystemWatcher project
/// </summary>
public partial class MainWindow : Window
{
#region Fields
private FileSystemWatcher _watcher = new FileSystemWatcher();
private ObservableCollection<string[]> _eventList = new ObservableCollection<string[]>();
#endregion
public MainWindow()
{
InitializeComponent();
Main.Content = new MonitorPage(ref _watcher, ref _eventList);
PageState();
}
private void PageState()
{
if (Main.Content.GetType() == typeof(MonitorPage))
{
Menu_MonitorButton.IsEnabled = false;
Menu_MonitorButton.Background = new SolidColorBrush(Color.FromRgb(88, 88, 95));
Menu_DataBaseButton.IsEnabled = true;
Menu_HelpButton.IsEnabled = true;
}
else if (Main.GetType() == typeof(DataBasePage))
{
Menu_MonitorButton.IsEnabled = true;
Menu_DataBaseButton.IsEnabled = false;
Menu_DataBaseButton.Background = new SolidColorBrush(Color.FromRgb(88, 88, 95));
Menu_HelpButton.IsEnabled = true;
}
else
{
Menu_MonitorButton.IsEnabled = true;
Menu_DataBaseButton.IsEnabled = true;
Menu_HelpButton.IsEnabled = false;
Menu_HelpButton.Background = new SolidColorBrush(Color.FromRgb(88, 88, 95));
}
}
private void Menu_MonitorButton_Click(object sender, RoutedEventArgs e)
{
PageState();
Main.Content = new MonitorPage(ref _watcher, ref _eventList);
}
private void MenuStrip_DataBaseButton_Click(object sender, RoutedEventArgs e)
{
PageState();
Main.Content = new DataBasePage(ref _eventList);
}
private void MenuStrip_HelpButton_Click(object sender, RoutedEventArgs e)
{
PageState();
Main.Content = new HelpPage();
}
}
}
XAML:
<Window x:Name="Home" x:Class="EyeInTheSky.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:EyeInTheSky"
xmlns:System="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="Eye In The Sky - Windows File System Watcher" Height="450" Width="1105" WindowStartupLocation="CenterScreen" ResizeMode="NoResize" TextOptions.TextFormattingMode="Ideal" Background="#FF39393E" Foreground="#FFE4E4E4" FontFamily="Roboto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="27*"/>
<RowDefinition Height="394*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="240*"/>
<ColumnDefinition Width="859*"/>
</Grid.ColumnDefinitions>
<Frame x:Name="Main" Height="421" VerticalAlignment="Top" Grid.RowSpan="2" Grid.ColumnSpan="2" Panel.ZIndex="1"/>
<DockPanel HorizontalAlignment="Left" Height="27" LastChildFill="False" VerticalAlignment="Top" Width="240" Panel.ZIndex="10000">
<StackPanel x:Name="Menu" Orientation="Horizontal" HorizontalAlignment="Left" Height="27" VerticalAlignment="Top" Width="240" Background="#FF4E4E53">
<Button x:Name="Menu_MonitorButton" Content="Monitor" Width="80" Click="Menu_MonitorButton_Click" Background="#FF4E4E53" BorderBrush="#FF585858" Foreground="LightGray" BorderThickness="1,0"/>
<Button x:Name="Menu_DataBaseButton" Content="Data Base" Width="80" Click="MenuStrip_DataBaseButton_Click" Background="#FF4E4E53" BorderBrush="#FF585858" Foreground="LightGray" BorderThickness="1,0"/>
<Button x:Name="Menu_HelpButton" Content="About" Width="80" Click="MenuStrip_HelpButton_Click" Background="#FF4E4E53" BorderBrush="#FF585858" Foreground="LightGray" Padding="0,1,1,1" BorderThickness="1,0,2,0"/>
</StackPanel>
</DockPanel>
</Grid>
</Window>

Window.ShowDialog failes on return

I have a custom input dialog box that request an user's name and a reson (because reasons) for doing a certain action in my application. The user clicks on a button on the main window and the dialog box shows, as it should.
The user then enters his/her name and the reason and clicks ok. The dialog then closes but I ( the program) never receives an answer. Here is my XAML for the input dialog:
<Window x:Class="Sequence_Application_2.GUI.ForcedRackInput"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Forcera Rack" Height="300" Width="300"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="21*"/>
<ColumnDefinition Width="274*"/>
</Grid.ColumnDefinitions>
<TextBox Name="OperatorNameText" HorizontalAlignment="Left" Height="23" Margin="15,36,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Grid.ColumnSpan="2"/>
<Label x:Name="label" Content="Namn:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Grid.ColumnSpan="2"/>
<Label x:Name="label1" Content="Orsak:" HorizontalAlignment="Left" Margin="10,72,0,0" VerticalAlignment="Top" Grid.ColumnSpan="2"/>
<Border BorderThickness="1" BorderBrush="Black" Grid.ColumnSpan="2" Margin="0,0,0,0.5">
<TextBox Name="ReasonText" Margin="15,98,15,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="116" />
</Border>
<Button Name="OkButton" IsDefault="True" Content="OK" Click="OkButtonPressed" HorizontalAlignment="Left" Margin="26.202,233,0,0" VerticalAlignment="Top" Width="75" Cursor="Arrow" Grid.Column="1"/>
<Button Name="CancelButton" IsCancel="True" Content="Avbryt" Margin="152.202,233,47,0" VerticalAlignment="Top" Cursor="Arrow" Grid.Column="1"/>
</Grid>
</Window>
And here is the "behind code":
namespace Sequence_Application_2.GUI
{
using System.Windows;
public partial class ForcedRackInput : Window
{
public string OperatorName { get { return OperatorNameText.Text; } }
public string ForcedRackReason { get { return ReasonText.Text; } }
public ForcedRackInput()
{
InitializeComponent();
}
private void OkButtonPressed(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
}
}
and this is how I call the code (from a model, not a "window class")
public void ForceClosingRack(Flow forcedFlow)
{
var forcedRackWindow = new ForcedRackInput();
string operatorName = "";
string reasonForForced = "";
if( forcedRackWindow.ShowDialog() == true)
{
operatorName = forcedRackWindow.OperatorName;
reasonForForced = forcedRackWindow.ForcedRackReason;
}
} // code jumps from "if(forcedRackWindow.... to this line when ok is clicked in the dialog
Looked for the solution for some time now and I just about to change career
Thanks for your time
My guess is that the problem doesn't lie in the code, which seems to be fine, but in your if statement.
When you run your program in Debug mode it should work as expected.
My guess is that you are assigning the variables operatorName and reasonForForced inside your if statment but they are not used anywhere else in the program and hence the whole if statement is ignored by the compiler and not present when running in Release mode.
A small modification in your code which embeds different behaviour depending on the variable values can prove my guess:
private void Button_Click(object sender, RoutedEventArgs e)
{
var forcedRackWindow = new ForcedWindow();
string operatorName = "foo";
string reasonForForced = "foo";
if (forcedRackWindow.ShowDialog() == true)
{
operatorName = forcedRackWindow.OperatorName;
reasonForForced = forcedRackWindow.ForcedRackReason;
}
if(!operatorName.Equals(reasonForForced))
{
MessageBox.Show("We are not the same");
}
}

Transfer a string from MainWindow to a RichTextBox in UserControl

I'm new in WPF, I have a UserControl that called Communication which responsible to connect \ disconnect to a SerialPort class.
Also, there is a LOG which is a RichTextBox and my purpose is to read and write strings which running on the SerialPort buffer, and display them on that log.
The Application looks like that:
Communication XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0"
Orientation="Horizontal"
HorizontalAlignment="Center"
Margin="0,0,0,10">
<TextBlock Text="Choose COM:"
VerticalAlignment="Center"
/>
<ComboBox Name="ComboBoxPorts"
Height="25"
Width="75"
VerticalContentAlignment="Center"
SelectionChanged="ComboBoxPorts_SelectionChanged" />
<Button Name="Button_open_port"
Content="Connect"
Height="25"
Click="open_port_Click"/>
</StackPanel>
<Border BorderThickness="1" BorderBrush="Black" Grid.Row="1">
<ScrollViewer Name="ScrollViewer_LogView"
VerticalScrollBarVisibility="Auto"
Height="220">
<RichTextBox Name="RichTextBox_logView"
Height="220"
VerticalScrollBarVisibility="Visible" />
</ScrollViewer>
</Border>
</Grid>
Also in Code of that UserControl I have function which called "Print to log" that works and print on the LOG the strings that I'm giving her.
Communication CS Code:
public partial class Communication : UserControl
{
public SerialPort mySerialPort = new SerialPort();
public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e);
public event DataReceivedEventHandler DataReceivedEvent;
public Communication()
{
InitializeComponent();
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
}
private void open_port_Click(object sender, RoutedEventArgs e)
{
// If Close
if (mySerialPort.IsOpen == false)
{
mySerialPort.PortName = ComboBoxPorts.SelectedItem.ToString();
mySerialPort.Open();
Button_open_port.Background = new SolidColorBrush(Colors.Tomato);
Button_open_port.Content = "Disconnect";
}
// If Open
else
{
mySerialPort.Close();
Button_open_port.Background = new SolidColorBrush(Colors.LightGreen);
Button_open_port.Content = "Connect";
}
}
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
// Print it on the Log
Print_To_Log(indata, System.Windows.Media.Brushes.Red, 0);
}
/// <param name="data">string of the data</param>
/// <param name="color">object "Brushes.xxxxx" -> (xxxxx=name of the color)</param>
/// <param name="direction">1 for TX (sending data), 0 or anything else for RX(receiveing data)</param>
public void Print_To_Log(string data, SolidColorBrush color, int direction = 0)
{
// Print it on the Log
RichTextBox_logView.Dispatcher.BeginInvoke((Action)delegate()
{
TextRange rangeOfTextInput = new TextRange(RichTextBox_logView.Document.ContentEnd, RichTextBox_logView.Document.ContentEnd);
if (direction == 1)
rangeOfTextInput.Text = ">> ";
else
rangeOfTextInput.Text = "<< ";
rangeOfTextInput.ApplyPropertyValue(TextElement.ForegroundProperty, color);
RichTextBox_logView.AppendText(data + "\r");
RichTextBox_logView.ScrollToEnd();
});
}
I have a MainWindow that contains TextBox and Button. Also that MainWindow contains in the XAML the UserControl Communication.
I want be able to write a string on that TextBox, and after clicking the button "Send", transfer the string to the SerialPort (which appears in the UserControl) and it will appears on the LOG.
Also, when I receive something on the SerialPort, it should also appears on that LOG.
How I'm doing that? Please Help.
MainWindow XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<MyProject:Communication Grid.Row="0"
Margin="0,10"
Width="450"
Height="250"/>
<WrapPanel Grid.Row="1">
<TextBox Name="TextBox_input"
Width="200"
HorizontalAlignment="Left"
Margin="50,0,20,0"/>
<Button Name="Button_send"
Width="80"
Content="_Send"
Click="Button_send_Click"/>
</WrapPanel>
</Grid>
MainWindow code:
public MainWindow()
{
InitializeComponent();
}
private void Button_send_Click(object sender, RoutedEventArgs e)
{
}
what you can is you can give Name property to that particular usercontrol which u had added in your mainwindow.xaml and then can get the think
--> Assign Name Property to userControl
By adding x:Name="ucCommunication" to your MyProject:Communication object.
--> Now Make Necessary changes to the UserControl
(Make one Helper Function)
public void GetStringDataFromControl(string content)
{
///write here your required function to execute when u get send button clicked and had textbox text in hand
}
--> Now Pass RichTextbox Text to your UserControl by calling public member function like this
private void Button_send_Click(object sender, RoutedEventArgs e)
{
//here call usecontrol helper function
ucCommunication.GetStringDataFromControl("write the string you want to pass.Here in your case get richtextbox text and convert it to string and pass");
}
In case of any query or concern please let me. If it really helps then please mark it as answer.

How to use (if possible) same source a tap event uses in a ContextMenu button click?

Im tweaking a Sound Player app to try and include a Save as Ringtone function. App uses Tiles and a Viewmodel. Tapping each tile plays a sound. I added a Context Menu to the Data Template to give the option on a Tap and Hold event to save that sound as a Ringtone. I am having some issues figuring out just how to use the same source as the Tiles use to play the sound. Below, first code is portion of the Mainpage.xaml. Then the c# code. What I have set at the bottom of the MainPage.cs for the _customRingtone Source is wrong. The emulator stops at "SoundData data = selector.SelectedItem as SoundData;" I cant figure out how to do the source in a similar way the Tile taps get the audio for playing it. I didnt post the ViewModel but can if you want me to. That is where the Tile Groups and sounds are loaded.
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="SoundTileDataTemplate">
<StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Click="Save_Click" Header="Save as Ringtone" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<Grid Background="{StaticResource PhoneAccentBrush}"
Margin="0, 0, 12, 12">
<Grid VerticalAlignment="Top"
HorizontalAlignment="Right"
Width="40"
Height="40"
Margin="0, 6, 6, 0">
<Ellipse Stroke="{StaticResource PhoneForegroundBrush}"
StrokeThickness="3" />
<Image Source="/Assets/AppBar/Play.png" />
</Grid>
<StackPanel VerticalAlignment="Bottom">
<TextBlock Text="{Binding Title}" Margin="6, 0, 0, 6" />
</StackPanel>
</Grid>
</StackPanel>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<MediaElement
Name="AudioPlayer"
Volume="1" />
<!--Pivot Control-->
<phone:Pivot Title="{Binding Path=LocalizedResources.ApplicationTitle,
Source={StaticResource LocalizedStrings}}">
<phone:PivotItem Header="{Binding Animals.Title}">
<phone:LongListSelector x:Name="Animal"
SelectionChanged="LongListSelector_SelectionChanged"
Margin="0,0,-12,0"
ItemsSource="{Binding Animals.Items}"
LayoutMode="Grid"
GridCellSize="150,150"
ItemTemplate="{StaticResource SoundTileDataTemplate}"
/>
</phone:PivotItem>
public partial class MainPage : PhoneApplicationPage
{
private readonly SaveRingtoneTask
_CustomRingtone;
// Constructor
public MainPage()
{
InitializeComponent();
// Set the data context of the listbox control to the sample data
DataContext = App.ViewModel;
_CustomRingtone = new SaveRingtoneTask();
_CustomRingtone.Completed +=
customeRingtone_Completed;
BuildLocalizedApplicationBar();
}
// Load data for the ViewModel Items
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
}
}
private void LongListSelector_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
LongListSelector selector = sender as LongListSelector;
// verifying our sender is actually a LongListSelector
if (selector == null)
return;
SoundData data = selector.SelectedItem as SoundData;
// verifying our sender is actually SoundData
if (data == null)
return;
private void customeRingtone_Completed(object sender, TaskEventArgs e)
{
if (e.TaskResult == TaskResult.OK)
{
MessageBox.Show(#"Saved");
}
else if (e.TaskResult == TaskResult.Cancel)
{
MessageBox.Show(#"Canceled");
}
else
{
MessageBox.Show(#"Not Saved");
}
}
private void Save_Click(object sender, System.Windows.RoutedEventArgs e)
{
LongListSelector selector = sender as LongListSelector;
SoundData data = selector.SelectedItem as SoundData;
**_CustomRingtone.Source = new Uri(data.FilePath, UriKind.RelativeOrAbsolute**);
_CustomRingtone.DisplayName = "Ring";
_CustomRingtone.Show();
}
You Save_Click event handler is not passed a LLS, but a context MenuItem. The DataContext of the MenuItem is the object you are after.
private void Save_Click(object sender, System.Windows.RoutedEventArgs e)
{
var element = (FrameworkElement)sender;
SoundData data = element.DataContext as SoundData;
_CustomRingtone.Source = new Uri(data.FilePath, UriKind.RelativeOrAbsolute**);
_CustomRingtone.DisplayName = "Ring";
_CustomRingtone.Show();
}

Windows phone 8 and header with keyboard

So I have a really huge problem:
On my page (It’s about the same as a "messages app" from Microsoft), when I click on my input box and keyboard pop up, my header is moved up and no longer visible.
I’ve searched a little and most of solutions I’ve found were not working (targeting wp7 for them...) . (Like a blog where guy creates a lot of dependency property for then margin of Phoneframe is changed. It works, a little, but the header goes off during animation of keyboard. It’s not enough, it’s really not perfect. )
The Microsoft manages it in standard “Messages” app (With a little bug of font size changing), so it must be possible.
How can realize that ?
I tried this solution and it works just fine :
Try to listen to the TextBox.GotFocus and TextBox.LostFocus events to detect when a TextBox in your application acquires and looses focus.
Put your whole content in a ScrollViewer just as follows :
Code XAML :
<ScrollViewer x:Name="LayoutRoot" Margin="0,0,0,0">
<Grid Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
<TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1">
<TextBox HorizontalAlignment="Left" Height="254" Margin="10,183,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="456" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus"/>
</Grid>
</Grid>
</ScrollViewer>
Adding the content in a ScrollViewer will give the experience of scrolling even when the keyboard is not open, and that's not really desirable.
For that you need to disable scrolling before the Keyboard is opened and after the keyboard is closed.
In the TextBox_GotFocus event play on the top margin of the ScrollViewer :
in the constructor :
public MainPage()
{
InitializeComponent();
LayoutRoot.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled;
}
the events :
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
LayoutRoot.Margin = new Thickness(0, 330, 0, 0);
LayoutRoot.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
}
Add the TextBox_LostFocus event handler also to get the page back to its original view when the keyboard is closed :
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
LayoutRoot.Margin = new Thickness(0, 0, 0, 0);
LayoutRoot.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled;
}
This helps you get the page to its somehow original position when the keyboard is opened.
Hope this helped.
You can make the UI as listbox so that you can scroll the listbox and check the header which is gone up.
When SIP keyboard is rendered, PhoneApplicationFrame.TranslateTransform.Y is set to specific values (-259 in landscape orientation, -339 in portrait orientation). To update layout, we’ll just set top margin to the specified value(-s) and after that Silverlight layout system will fix the issue.
here XAML part:
<Grid x:Name="LayoutRoot" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="WINDOWS PHONE" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Text="developer's ?" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid Grid.Row="1" Margin="12,0,12,0"></Grid>
<TextBox Grid.Row="2" LostFocus="TextBoxLostFocus"/>
</Grid>
C# portions
private const double LandscapeShift = -259d;
private const double LandscapeShiftWithBar = -328d;
private const double Epsilon = 0.00000001d;
private const double PortraitShift = -339d;
private const double PortraitShiftWithBar = -408d;
public static readonly DependencyProperty TranslateYProperty = DependencyProperty.Register("TranslateY", typeof(double), typeof(MainPage), new PropertyMetadata(0d, OnRenderXPropertyChanged));
public MainPage()
{
InitializeComponent();
Loaded += MainPageLoaded;
}
public double TranslateY
{
get { return (double)GetValue(TranslateYProperty); }
set { SetValue(TranslateYProperty, value); }
}
private static void OnRenderXPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MainPage)d).UpdateTopMargin((double)e.NewValue);
}
private void MainPageLoaded(object sender, RoutedEventArgs e)
{
BindToKeyboardFocus();
}
private void BindToKeyboardFocus()
{
PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;
if (frame != null)
{
var group = frame.RenderTransform as TransformGroup;
if (group != null)
{
var translate = group.Children[0] as TranslateTransform;
var translateYBinding = new Binding("Y");
translateYBinding.Source = translate;
SetBinding(TranslateYProperty, translateYBinding);
}
}
}
private void UpdateTopMargin(double translateY)
{
if(IsClose(translateY, LandscapeShift) || IsClose(translateY,PortraitShift) || IsClose(translateY, LandscapeShiftWithBar) || IsClose(translateY, PortraitShiftWithBar))
{
LayoutRoot.Margin = new Thickness(0, -translateY, 0, 0);
}
}
private bool IsClose(double a, double b)
{
return Math.Abs(a - b) < Epsilon;
}
private void TextBoxLostFocus(object sender, RoutedEventArgs e)
{
LayoutRoot.Margin = new Thickness();
}
You can try following link. I think it will be helpful.
http://sorokoletov.com/2011/08/windows-phone-70-handling-text-entry-screens/

Categories

Resources