Show alternately text and image at the center - c#

Here is piece of my code:
<StackPanel Orientation="Vertical" Grid.Row="0" Grid.Column="0" >
<Image HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Collapsed" Stretch="None" Name="BImage" Grid.Row="0" Margin="10 100 10 10">
</Image>
<TextBlock Margin="10 0 10 0" Name="InnerContent" FontSize="45" TextWrapping="Wrap" Text=" "/>
What I would like to achieve is to show BImage and InnerContent alternately but text should be always in the center of the image space so that when image is replaced by text, text is in the middle of the space of the image.
And when this is done I would like to add another TextBlock called errorTextBlock and it should be always visible just below BImage or InnerContent according to which one is visible right now.
I hope that it's clear

May be this could help.
public System.Windows.Threading.DispatcherTimer _timer = new System.Windows.Threading.DispatcherTimer();
_timer.Tick += _timer_Tick;
_timer.Interval = new TimeSpan(0,0,1);
_timer.Start();
int second = 0; // a local variable to keep tab on alternate visibility of elements per second in _timer_Tick
void _timer_Tick(object sender, EventArgs e)
{
second++;
if((second % 2) == 0)
{
InnerContent.Visibility = System.Windows.Visibility.Hidden;
BImage.Visibility = System.Windows.Visibility.Visible;
}
else
{
BImage.Visibility = System.Windows.VisibilityHidden;
InnerContent.Visibilty = System.Windows.Visibility.Visible;
}
}

Related

How can I drag and drop controls using a common method?

I have the following XAML code, which creates two stack panels within a big parent Stack Panel. I would like to be able to drag each small stack panel within the parent bigStack panel.
XAML
<StackPanel BorderThickness="1" BorderBrush="Black" x:Name="bigStack">
<StackPanel x:Name="smallStack1" ManipulationMode="All" ManipulationDelta="objectManipulationDelta" ManipulationStarting="objectManipulationStarting">
<TextBlock Text="John Doe"/>
<TextBlock Text="CEO"/>
</StackPanel>
<StackPanel x:Name="smallStack2" ManipulationMode="All" ManipulationDelta="objectManipulationDelta" ManipulationStarting="objectManipulationStarting">
<TextBlock Text="Jane Doe"/>
<TextBlock Text="CTO"/>
</StackPanel>
</StackPanel>
C# backend:
private TranslateTransform dragtranslation ;
private void objectManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
dragtranslation.X += e.Delta.Translation.X;
dragtranslation.Y += e.Delta.Translation.Y;
}
private void objectManipulationStarting(object sender, ManipulationStartingRoutedEventArgs e)
{
var stackDragged = e.OriginalSource as StackPanel;
dragtranslation = new TranslateTransform();
stackDragged.RenderTransform = this.dragtranslation ;
}
Original Code found here (Official Microsoft UWP Documentation) but adapted (obviously wrongly) to suit my needs
PROBLEM 1
1) Drag smallStack1 for the first time: OK
2) Drag smallStack2 for the second time: Reverts back to the original position
PROBLEM 2
1) Drag smallStack1 for the first time: OK
2) Drag smallStack2 for the first time: OK
3) Drag either of the smallStacks again: Reverts back to the original position
You can check the problems in the .gif below:
WHAT I WISH TO ACCOMPLISH
Drag the controls using a common method, because I plan to dynamically create more controls inside the bigStack panel.
You are basically reinstantiating TranslateTransform everytime you click on an Item. That is the reason why when you click on the item second time, it navigates back to 0,0 which is the original position for TranslateTransform.
To Handle this in a easier way, this is what I would do.
1) I would give explicit TranslateTransform to the smallStackPanel's
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel BorderThickness="1" BorderBrush="Black" x:Name="bigStack">
<StackPanel x:Name="smallStack1" ManipulationMode="All" ManipulationDelta="objectManipulationDelta" >
<StackPanel.RenderTransform>
<TranslateTransform />
</StackPanel.RenderTransform>
<TextBlock Text="John Doe"/>
<TextBlock Text="CEO"/>
</StackPanel>
<StackPanel x:Name="smallStack2" ManipulationMode="All" ManipulationDelta="objectManipulationDelta" >
<StackPanel.RenderTransform>
<TranslateTransform />
</StackPanel.RenderTransform>
<TextBlock Text="Jane Doe"/>
<TextBlock Text="CTO"/>
</StackPanel>
</StackPanel>
</Grid>
And then all i need to do in codebehind is handle ManipulationDelta.
private void objectManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
var stackDragged = e.OriginalSource as StackPanel;
(stackDragged.RenderTransform as TranslateTransform).X += e.Delta.Translation.X;
(stackDragged.RenderTransform as TranslateTransform).Y += e.Delta.Translation.Y;
}
Output:
Update
To add TranslateTransform from Code
StackPanel sp = new StackPanel();
sp.RenderTransform = new TranslateTransform();
Good Luck.

Resizing Microsoft Ads

Hi I use Microsofts Ads in my UWP app and I want the ads to resize after the with of the app but cant get it to work.
I understand the ad control must be on of the valid sizes (as described here) so I wrote this code to resize the ad:
private void panel_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.NewSize.Width >= 728)
{
ad.Width = 728;
ad.Height = 90;
}
else if (e.NewSize.Width >= 640)
{
ad.Width = 640;
ad.Height = 100;
}
else if (e.NewSize.Width >= 480)
{
ad.Width = 480;
ad.Height = 80;
}
else if (e.NewSize.Width >= 320)
{
ad.Width = 320;
ad.Height = 50;
}
else if (e.NewSize.Width >= 300)
{
ad.Width = 300;
ad.Height = 50;
}
}
This made the control resize accordingly but the ad inside the control looked terrible. I added ad.Refresh(); at the end but that didn't change a thing.
Does anybody know what to do?
I have faced your same problem.
Unfortunately, the Ads are loaded every 30 seconds and you can not refresh them more then once in 30 seconds.
This is the reason because the call to the Refresh() method fails.
I used a workaround that I hope it can help you.
I have "covered" the Ad with a StackPanel of the same size (and position) of the Ad. I have showed this panel when I had to change the size of the Ad.
At the refresh of the Ad (you can intercept it by the callback AdRefreshed), I have hidden the cover panel.
<StackPanel x:Name="AdsCover" Width="300" Height="50" Visibility="Visible"
Grid.Column="0" Grid.ColumnSpan="3" HorizontalAlignment="Left" VerticalAlignment="Bottom" Canvas.ZIndex="12" Background="WhiteSmoke">
<Border x:Name="AdsBorder" BorderBrush="{x:Null}" Height="50">
<TextBlock x:Name="AdsLoading" Text="Ads Loading..." HorizontalAlignment="Center" FontStyle="Italic" FontFamily="Calibri" FontSize="24"
TextAlignment="Center" VerticalAlignment="Center"/>
</Border>
</StackPanel>
<UI:AdControl x:Name="adsMS"
ApplicationId="3f83fe91-d6be-434d-a0ae-7351c5a997f1"
AdUnitId="10865270"
HorizontalAlignment="Left"
Height="50"
VerticalAlignment="Bottom"
Width="300"
Grid.Column="0" Grid.ColumnSpan="3"
Canvas.ZIndex="10"
ErrorOccurred="OnAdErrorOccurred"
AdRefreshed="OnAdRefreshed"/>
In the code behind, where you have to change the Ad size, you can do this:
...
// Change the size of the Ad. adsW and adsH are the new size
adsMS->SetValue(WidthProperty, 1.0*adsW);
adsMS->SetValue(HeightProperty, 1.0*adsH);
// Cover panel with the same size
AdsCover->SetValue(WidthProperty, 1.0*adsW);
AdsCover->SetValue(HeightProperty, 1.0*adsH);
AdsBorder->SetValue(HeightProperty, 1.0*adsH);
// If the size are changed, I hide the Ad with the panel.
// In this way, I can avoid to see the deformed Ad.
// m_previousAdsWidth and m_previousAdsHeight are the previous size
// of the Ad.
if ((m_previousAdsWidth != adsW || m_previousAdsHeight != adsH)
&& m_previousAdsWidth > 0 && m_previousAdsHeight > 0)
{
AdsCover->SetValue(VisibilityProperty, Windows::UI::Xaml::Visibility::Visible);
}
m_previousAdsWidth = adsW;
m_previousAdsHeight = adsH;
...
In the callback OnAdRefreshed() you can hide the panel
// Called when the Ad is refreshed.
void DirectXPage::OnAdRefreshed(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
// If the Ad is hidden by the cover panel, I will make it visible again.
if (AdsCover->Visibility == Windows::UI::Xaml::Visibility::Visible)
AdsCover->SetValue(VisibilityProperty, Windows::UI::Xaml::Visibility::Collapsed);
}

How to access controls, which are in the ControlTemplate

In my WP8 appliciation's App.xaml file I've defined ControlTemplate as following:
<Application.Resources>
<ControlTemplate x:Name="AddReminderDialog">
<Canvas HorizontalAlignment="Center" Height="320" Width="260"
VerticalAlignment="Center" Background="White" Margin="110,178,110,238">
<TextBlock Foreground="Black" Text="Напомнить" FontSize="15" HorizontalAlignment="Center" Canvas.Left="92" Canvas.Top="38" />
<Button Name="btn1HourBef" BorderThickness="0" Click="NotificationButtonClick" Background="Black" Content="За час" Width="260" FontSize="15" Height="60" Margin="0,70,0,0"/>
<Button Name="btn30MinBef" BorderThickness="0" Click="NotificationButtonClick" Background="Black" Content="За 30 минут" Width="260" FontSize="15" Height="60" Margin="0,130,0,0"/>
<Button Name="btnOnArrDept" BorderThickness="0" Click="NotificationButtonClick" Background="Black" Content="По прилету/вылету" Width="260" FontSize="15" Height="60" Margin="0,190,0,0"/>
<Button Name="btnCancel" BorderThickness="0" Click="NotificationButtonClick" Background="Black" Content="Отменить" Width="260" FontSize="15" Height="60" Margin="0, 250, 0, 0" Visibility="Collapsed"/>
</Canvas>
</ControlTemplate>
</Application.Resources>
I use it as a template of popup as following
private void Image_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
var image = sender as Image; //get the sender iamge
var modelItem = image.DataContext; //get image's data context
const double width = 260;
const double height = 280;
//get the flight id from image's tag property(which was binded in flightInfoDataTemplate)
flightID = Convert.ToString(image.Tag);
//define content for popup
var content = new ContentControl()
{
Width = width,
Height = height,
Background = new SolidColorBrush(Colors.Transparent)
};
//set the template of content to the contentTemplate, which was defined in app.xaml
content.Template = (ControlTemplate)Resources["AddReminderDialog"];
//set popup's datacontext to the image's datacontext
content.DataContext = modelItem;
//popup's child property is setting to our content
popup.Child = content;
popup.Height = height;
popup.Width = width;
popup.VerticalOffset = Application.Current.RootVisual.RenderSize.Height / 2 - height / 2;
popup.HorizontalOffset = Application.Current.RootVisual.RenderSize.Width / 2 - width / 2;
popup.IsOpen = true;
}
I use this popup to set notification. When user taps the image in the first time the btnCancel button should be invisible, because there is nothing to cancel. When the image is tapped the second time, btnCancel should become visible to cancel the notification.
I've set button visibility to collapsed by default. But I have not idea how to access that button in the code behind to make it visible.
So my question is how can I change button's visibility settings in the code behind?
You can do something like this,
private void SearchElement(DependencyObject targeted_control)
{
var count = VisualTreeHelper.GetChildrenCount(targeted_control); // targeted_control is the Canvas
if (count > 0)
{
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(targeted_control, i);
if (child is Button ) // specific button control
{
// do your logic
}
}
}
}

How to make the canvas detect touch input properly in C#?

Basically, I'm trying to make the canvas listen for a touch input (tap) and will increment the number of taps on screen. It isn't working when I touch the screen on my device. I debugged my code and nothing seems out of the ordinary except that the touch is not detected. I checked ZIndex and the canvas is in front of the screen to be touchable. How do I make it work?
XAML:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBlock Name="counter" FontSize="150" HorizontalAlignment="Center" TextWrapping="Wrap" Text="0" VerticalAlignment="Center" Margin="188,10,187,397"/>
<Button Content="Reset" HorizontalAlignment="Stretch" Margin="-18,535,-18,0" VerticalAlignment="Top" Click="Button_Click"/>
<Canvas ZIndex="0" Name="Canvas" HorizontalAlignment="Center" Height="535" VerticalAlignment="Top" Width="446" MouseLeftButtonDown="Canvas_MouseLeftButtonDown" MouseLeftButtonUp="Canvas_MouseLeftButtonUp" MouseLeave="Canvas_MouseLeave"/>
</Grid>
C#:
int taps = 0; // create var to detect number of times, user touches the screen
// Constructor
public MainPage()
{
InitializeComponent();
}
// method to register the touch as the finger is placed on the screen
private void Canvas_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//Canvas c = sender as Canvas;
counter.Text = "TOUCHED!";
}
//method register the touch as the finger is lifting up from the screen
private void Canvas_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//Canvas c = sender as Canvas;
taps++;
counter.Text = taps.ToString(); //convert var from int to string
}
//method register the touch as the finger leaves the area of the screen
private void Canvas_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
//Canvas c = sender as Canvas;
MessageBox.Show("You left the screen without lifting your finger. That does not count as a tap!", "Caution!", MessageBoxButton.OK);
}
// method to reset the counter to zero when button is pressed and released
private void Button_Click(object sender, RoutedEventArgs e)
{
taps = 0; // reset the count
counter.Text = taps.ToString(); // convert var from int to string
}
I don't know why you want to do it with Canvas - it won't work as you have nothing in this Canvas, so it can't register your click/tap, Canvas is also hard to adjust to screen. I think it can be done simpler way if you want to do it with MouseUp/Down - subscribe directly to Grid containing your elements instead of filling this Grid with additional Canvas:
In XAML:
<Grid x:Name="ContentPanel" Margin="12,0,12,0" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="7*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<TextBlock Name="counter" FontSize="150" HorizontalAlignment="Center" TextWrapping="Wrap" Text="0" VerticalAlignment="Center" Grid.Row="0"/>
<Button Content="Reset" HorizontalAlignment="Stretch" VerticalAlignment="Center" Click="Button_Click" Grid.Row="1"/>
<TextBlock Name="Touched" FontSize="50" HorizontalAlignment="Center" TextWrapping="Wrap" Text="Touched" VerticalAlignment="Center" Visibility="Collapsed" Grid.Row="2"/>
</Grid>
In code behind:
private int taps = 0;
public MainPage()
{
InitializeComponent();
ContentPanel.MouseLeftButtonDown += ContentPanel_MouseLeftButtonDown;
ContentPanel.MouseLeftButtonUp += ContentPanel_MouseLeftButtonUp;
}
private void ContentPanel_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
taps++;
counter.Text = taps.ToString(); //convert var from int to string
Touched.Visibility = Visibility.Collapsed;
}
private void ContentPanel_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
Touched.Visibility = Visibility.Visible;
}
// method to reset the counter to zero when button is pressed and released
private void Button_Click(object sender, RoutedEventArgs e)
{
taps = 0; // reset the count
counter.Text = taps.ToString(); // convert var from int to string
}
As you can see I've subscribed to Grid events (which covers whole screen) - but to make it work I had to set its Background Brush to Transparent, otherwise it will work only if you touch text.
There are many other ways to make your App work, but I hope this will help.
Is there a reason why you don't use the touch-events?
Instead of using MouseLeftButtonDown and MouseLeftButtonUp you should use TouchDown and TouchUp.
Only when you don't handle the touch events or the manipulation events they will be mapped to mouse events. In my experience with touch a single tap also not always gets mapped to MouseLeftButtonDown. As far as I know you could also with mouse events only recoginse one finger. When you want to count more fingers it's necessary to use the TouchDown/TouchUp events.
The problem lies in the overlapping style of the grid
so either make grid rows or define a stackpanel inside the grid, something like this.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<stackpanel>
<TextBlock Name="counter" FontSize="150" HorizontalAlignment="Center" TextWrapping="Wrap" Text="0" Margin="0,0,0,0"/>
<Canvas ZIndex="0" Name="Canvas" HorizontalAlignment="Center" Height="535" VerticalAlignment="Top" Width="446" MouseLeftButtonDown="Canvas_MouseLeftButtonDown" MouseLeftButtonUp="Canvas_MouseLeftButtonUp" MouseLeave="Canvas_MouseLeave"/>
<Button Content="Reset" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Top" Click="Button_Click"/>
</stackpanel>
</Grid>
Try and check now.
You should set your Background property. If you don't want any background set it to Transparent:
<Canvas ZIndex="99" Background="Transparent" Name="Canvas" HorizontalAlignment="Center" Height="535" VerticalAlignment="Top" Width="446" Tapped="Canvas_CountMyTaps"/>
(If you want the canvas to be on Top be sure to make it have a greater ZIndex than the other elements that it overlaps)
If not set (the default value is null) the element won't capture any taps/click etc, it will be as if they "fall through".
Also, consider using the Tapped event which is a "higher level" event that will respond to clicks, taps with the finger, stylus, etc.

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