I have 2 pages, In first page when I click one of the item in listview, it should navigate to 2nd page and here in 2nd page snow particles are appeared.
After that, when I click back button, as usual it goes to first page and again when I click any of the listview items it navigates to 2nd page snow particles disappear,It just show a black screen.
Here are the codes:
For snow rendering I have two classes
First one
public class SnowScene : CCScene
{
CCParticleSnow snow;
public SnowScene(CCGameView gameView) : base(gameView)
{
var layer = new CCLayer();
layer.Color=new CCColor3B(new CCColor4B(20,30,50,10));
snow = new CCParticleSnow(new CCPoint(490, 20));
snow.Position = new CCPoint(490 / 2, 800 + 1);
snow.StartColor = new CCColor4F(CCColor4B.White);
snow.EndColor = new CCColor4F(CCColor4B.Red);
snow.StartSize = 15f;
snow.StartSizeVar = 2f;
snow.EndSize = 8f;
snow.EndSizeVar = 1f;
snow.Speed = 5f;
snow.Gravity = new CCPoint(0.5f, -2);
snow.EmissionRate = 3.5f;
snow.Life = 50f;
layer.AddChild(snow);
this.AddLayer(layer);
}
}
Second one
public class SnowyBackground : ContentView
{
SnowScene overallScene;
public SnowyBackground()
{
var sharpView = new CocosSharpView
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
};
sharpView.ViewCreated += (sender, e) =>
{
var ccGView = sender as CCGameView;
if (ccGView != null)
{
ccGView.DesignResolution = new CCSizeI(490, 800);
overallScene = new SnowScene(ccGView);
ccGView.RunWithScene(overallScene);
}
};
Content = sharpView;
}
}
And in Xaml in Second page
Now When I click an Item of listview in first page(page1) like below:
Event handler for Listview item click in first page-
async void Handle_ItemSelected(object sender, Xamarin.Forms.SelectedItemChangedEventArgs e)
{
try
{
await Navigation.PushModalAsync(new Page2(),false);
}
catch(Exception ex)
{ }
}
2nd page -
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Particle"
x:Class="Particle.ParticlePage">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<local:SnowyBackgroundView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.RowSpan="2" />
</Grid>
It navigates to page 2 and it successfully shows snow rendering. But when I repeat same steps... I mean If I click back button in page 2,then it goes to page1 and here when again I click lictview item,it goes to second page, but it doesnot show snow rendering, just a black screen.
Related
I'm trying in every way to get out of the loop that must create multiple RichTextBlockOverflow controls based on arbitrary input text length but without success. The HasOverflowContent property doesn't update either synchronously or asynchronously.
The variable bool "ThereIsText" I can not understand when and how to make it false to stop the loop.
The link with the text to paste in the paragraph "Run" is: text to paste.
MainPage.xaml:
<Page
x:Class="Text_Viewer_Test_UWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Text_Viewer_Test_UWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid x:Name="MenĂ¹" HorizontalAlignment="Left" Width="290" Padding="0" Margin="0,21,0,0">
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" x:Name="btnLoadText" Click="btnLoadText_Click" Content="Display text" HorizontalAlignment="Center" VerticalAlignment="Center" Width="270" Foreground="White" Height="32"/>
<TextBlock Grid.Row="1" x:Name="txtPage" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Grid>
<Grid x:Name="BaseGrid" Margin="320,10,30,10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Black">
<ScrollViewer x:Name="PageViewer" Background="White" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Visible" VerticalScrollMode="Disabled" HorizontalScrollMode="Enabled">
<StackPanel x:Name="StackViewer" VirtualizingStackPanel.VirtualizationMode="Recycling" Orientation="Horizontal"/>
</ScrollViewer>
</Grid>
</Grid>
MainPage.xaml.cs:
public sealed partial class MainPage : Page
{
RichTextBlock TextOneRich = new RichTextBlock() { Margin = new Thickness(20) };
List<RichTextBlockOverflow> TextList = new List<RichTextBlockOverflow>();
bool ThereIsText = true;
public MainPage()
{
this.InitializeComponent();
StackViewer.Children.Add(TextOneRich);
TextOneRich.Width = 400;
TextOneRich.TextAlignment = TextAlignment.Justify;
}
private async void btnLoadText_Click(object sender, RoutedEventArgs e)
{
TextList.Clear();
TextOneRich.Blocks.Clear();
StackViewer.Children.Clear();
StackViewer.Children.Add(TextOneRich);
Paragraph paragraphText = new Paragraph();
paragraphText.Inlines.Clear();
paragraphText.Inlines.Add(new Run { Text = "PasteTextHere" });
await Task.Run(async () =>
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
TextOneRich.Blocks.Add(paragraphText);
});
}).ContinueWith(async t =>
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
TextList.Add(new RichTextBlockOverflow() { Width = 400, Margin = new Thickness(20) });
StackViewer.Children.Add(TextList[0]);
TextOneRich.OverflowContentTarget = TextList[0];
});
});
await Task.Run(async () =>
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
{
while (ThereIsText)
{
await Task.Run(async () =>
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
TextList.Add(new RichTextBlockOverflow() { Width = 400, Margin = new Thickness(20) });
StackViewer.Children.Add(TextList[TextList.Count - 1]);
TextList[TextList.Count - 2].OverflowContentTarget = TextList[TextList.Count - 1];
txtPage.Text = TextList.Count.ToString();
});
});
}
});
});
}
}
If you need to do a lot of manipulation of UI objects, and you want to keep the UI responsive while you do that(1) then you can generally just await for a single millisecond, which will allow the UI to process any input messages etc.
Trying to access the HasOverflowContent property is problematic since it requires a layout pass to complete, and that could take an arbitrary amount of time. We could just await an arbitrary amount of time - say 50ms - but that wouldn't be ideal. Instead, you can use a technique similar to the one from "Waiting for XAML layout to complete" with a slight adjustment.
This XAML and code adds 1000 lines of text to a set of RichTextBlock / RichTextBlockOverflow controls and does so while keeping the UI responsive (the ball keeps moving, and you can scroll the list at any time):
XAML:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Margin="20" HorizontalAlignment="Stretch" x:Name="container">
<Ellipse Width="20" Height="20" Margin="0, 5" Fill="red"
x:Name="animation" HorizontalAlignment="Left"/>
<Button Content="Go" Click="Go" Margin="0,0,0,5"/>
<ScrollViewer MaxHeight="500">
<StackPanel x:Name="thePanel"/>
</ScrollViewer>
</StackPanel>
</Grid>
Code:
public static class Extensions
{
// This helper function is essentially the same as this answer:
// https://stackoverflow.com/a/14132711/4184842
//
// It adds an additional forced 1ms delay to let the UI thread
// catch up.
public static Task FinishLayoutAsync(this FrameworkElement element)
{
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
// Setup handler that will be raised when layout has completed.
EventHandler<object> handler = null;
handler = (s, a) =>
{
element.LayoutUpdated -= handler;
tcs.SetResult(true);
};
element.LayoutUpdated += handler;
// Await at least 1 ms (to force UI pump) and until the Task is completed
// If you don't wait the 1ms then you can get a 'layout cycle detected' error
// from the XAML runtime.
return Task.WhenAll(new[] { Task.Delay(1), tcs.Task });
}
}
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
// Simple animation to show the UI is not frozen
BadUiAnimation_DontDoThis();
}
// Very VERY bad way of doing animation, but it shows
// that the UI is still responsive. Normally you should
// use StoryBoards to do animation.
void BadUiAnimation_DontDoThis()
{
DispatcherTimer dt = new DispatcherTimer();
dt.Interval = TimeSpan.FromMilliseconds(33);
int delta = 4;
const int width = 20;
dt.Tick += (s, a) =>
{
var leftOffset = animation.Margin.Left;
if (leftOffset + delta < 0)
{
delta *= -1;
leftOffset = 0;
}
else if (leftOffset + delta + width > container.ActualWidth)
{
delta *= -1;
leftOffset = container.ActualWidth - width;
}
else
{
leftOffset += delta;
}
animation.Margin = new Thickness(leftOffset, 5, 0, 5);
};
dt.Start();
}
private async void Go(object sender, RoutedEventArgs e)
{
// Helper function
void AppendSimpleString(string s)
{
RichTextBlock rtb = new RichTextBlock();
rtb.Blocks.Add(CreateParagraphWithText(s));
thePanel.Children.Add(rtb);
}
// Another helper function
Paragraph CreateParagraphWithText(string s)
{
var p = new Paragraph();
var r = new Run();
r.Text = s;
p.Inlines.Add(r);
return p;
}
// Disable the button so you can't click it again until the
// insertion is over
(sender as Button).IsEnabled = false;
thePanel.Children.Clear();
AppendSimpleString($"Begin...{Environment.NewLine}");
// Generate some dummy strings to add to the page
var strings = new StringBuilder();
for (int i = 0; i < 1000; i++)
strings.Append($"This is line {i + 1}{Environment.NewLine}");
string text = strings.ToString();
// Create initial block with far too much text in it
var source = new RichTextBlock();
source.MaxHeight = 100;
source.Blocks.Add(CreateParagraphWithText(text));
thePanel.Children.Add(source);
// Create the first overflow and connect it to the original textblock
var prev = new RichTextBlockOverflow
{
MaxHeight = 100,
Margin = new Thickness(0, 10, 0, 0)
};
thePanel.Children.Add(prev);
source.OverflowContentTarget = prev;
// Wait for layout to complete so we can check the
// HasOverflowContent property
await prev.FinishLayoutAsync();
// Keep creating more overflows until there is no content left
while (prev.HasOverflowContent)
{
var next = new RichTextBlockOverflow
{
MaxHeight = 100,
Margin = new Thickness(0, 10, 0, 0)
};
thePanel.Children.Add(next);
prev.OverflowContentTarget = next;
// Wait for layout to complete, which will compute whether there
// is additional overflow (or not)
await prev.FinishLayoutAsync();
prev = next;
};
AppendSimpleString($"Done!{Environment.NewLine}");
// Enable interaction with the button again
(sender as Button).IsEnabled = true;
}
}
(1): Note that you probably want to do something to limit interaction with your UI while this is happening, which might require you to disable some controls or otherwise make sure the user doesn't mess with your app's state. The sample does this by disabling and then re-enabling the button.
I have got issues . Why did not it navigate to other xaml? Where is wrong?
So, I was trying to make it that can navigated between two or more xaml in a frame.
Here is link : https://github.com/Englbach/MutiViewInRootPage
<SplitView.Content>
<!-- OnNavigatingToPage we synchronize the selected item in the nav menu with the current page.
OnNavigatedToPage we move keyboard focus to the first item on the page after it's loaded. -->
<Frame x:Name="AppShellFrame">
<Frame.ContentTransitions>
<TransitionCollection>
<NavigationThemeTransition>
<NavigationThemeTransition.DefaultNavigationTransitionInfo>
<EntranceNavigationTransitionInfo />
</NavigationThemeTransition.DefaultNavigationTransitionInfo>
</NavigationThemeTransition>
</TransitionCollection>
</Frame.ContentTransitions>
</Frame>
</SplitView.Content>
public static AppShell Current = null;
public List<NavMenuItem> NavList { get; } = new List<NavMenuItem>(new[]
{
new NavMenuItem()
{
Symbol = Symbol.Add,
Label = "Add feed",
DestPage = typeof(RootPages),
Arguments = typeof(AddFeedView)
},
new NavMenuItem()
{
Symbol = Symbol.Edit,
Label = "Edit feeds",
DestPage = typeof(RootPages),
Arguments = typeof(EditFeedView)
}
});
public AppShell()
{
this.InitializeComponent();
Current = this;
}
private void NavMenuList_ItemInvoked(object sender, ListViewItem e)
{
NavMenuList.SelectedIndex = -1;
var item = (NavMenuItem)((NavMenuListView)sender).ItemFromContainer(e);
if(item!=null)
{
AppFrame.Navigate(typeof(RootPages), item.Arguments);
}
}
You probably followed the official Navigation menu (XAML) sample to design your layout.
There are two tiny problems in your demo.
Each time the items in the NavMenuList is clicked, the NavMenuList_ItemInvoked event in the AppShell.xaml.cs should be triggered. And in this event, you navigated again and again to your RootPages, and together pass the navigation parameter(item.Arguments) to the RootPages like this AppFrame.Navigate(typeof(RootPages), item.Arguments);, and the argument is actually your destination.
You can modify the code here like this:
private void NavMenuList_ItemInvoked(object sender, ListViewItem e)
{
//NavMenuList.SelectedIndex = -1;
var item = (NavMenuItem)((NavMenuListView)sender).ItemFromContainer(e);
if (item != null)
{
//AppFrame.Navigate(typeof(RootPages), item.Arguments);
if (item.DestPage != null &&
item.DestPage != this.AppFrame.CurrentSourcePageType)
{
this.AppFrame.Navigate(item.DestPage, item.Arguments);
}
}
}
Then here comes the second problem, as I said, the Arguments should be navigation parameter, for example, I navigate to AddFeedView page and I want to send a message "balalala", then we can code like this: AppFrame.Navigate(typeof(AddFeedView), "balalala");. This means, you confused with your DestPage and Arguments.
You can modify your NavList like this:
public List<NavMenuItem> NavList { get; } = new List<NavMenuItem>(new[]
{
new NavMenuItem()
{
Symbol = Symbol.Add,
Label = "Add feed",
DestPage = typeof(AddFeedView),
Arguments = typeof(RootPages)
},
new NavMenuItem()
{
Symbol = Symbol.Edit,
Label = "Edit feeds",
DestPage = typeof(EditFeedView),
Arguments = typeof(RootPages)
}
});
In additional, if you want your AppFrame to navigate to the RootPages at first by default, you can code like this:
public AppShell()
{
this.InitializeComponent();
Current = this;
AppFrame.Navigate(typeof(RootPages));
}
How can I position a button img randomly on a grid in XAML? I tried it, but it doesn't work!
This is my code:
public void randomButton()
{
Button newBtn = new Button();
newBtn.Content = "A New Button";
panelButton.Children.Add(newBtn);
Grid.SetRow(newBtn, 1);
Random generator = new Random();
newBtn = generator.Next(1, 100);
}
You need to set the Grid.Row dependency property on the Button.
XAML
<Window x:Class="WpfApplication1.MainWindow" [...] Loaded="Window_Loaded">
<Grid Name="grdMain">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
</Grid>
</Window>
C#
using System;
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
void Window_Loaded(object sender, RoutedEventArgs e)
{
//creating the button
Button b = new Button() { Content = "Click me!" };
//when clicked, it'll move to another row
b.Click += (s, ea) => ChangeButtonRow(s as Button);
//adding the button to the grid
grdMain.Children.Add(b);
//calling the row changing method for the 1st time, so the button will appear in a random row
ChangeButtonRow(b);
}
void ChangeButtonRow(Button b)
{
//setting the Grid.Row dep. prop. to a number that's a valid row index
b.SetValue(Grid.RowProperty, new Random().Next(0, grdMain.RowDefinitions.Count));
}
}
}
I hope this helps. :)
Problem while programmatically generating buttons in a user control of windows phone, and using this user control to mainpage.xaml but there are no buttons shown when application runs.
here is the code snippet which i am using, Thanks !
usercontrol.xaml:
<ScrollViewer >
<StackPanel x:Name="Panel">
<ContentControl x:Name="container"></ContentControl>
</StackPanel>
</ScrollViewer>
usercontrol.xaml.cs:
public LoginInterfaceControl()
{
InitializeComponent();
this.container = new ContentControl();
this.Panel = new StackPanel();
}
public LoginInterfaceControl(string Api_key)
{
InitializeComponent();
this.Panel = new StackPanel();
this.container = new ContentControl();
loginWP_DownloadString(Api_key);
}
public async void loginWP_DownloadString(string key)
{
InitializeComponent();
string cont;
using (HttpClient client = new HttpClient())
{
var result = await client.GetAsync("http://cdn.loginradius.com/interface/json/" + key + ".json");
if (result.StatusCode == HttpStatusCode.OK)
{
cont = await result.Content.ReadAsStringAsync();
MessageBox.Show(cont);
}
else
{
cont = await result.Content.ReadAsStringAsync();
MessageBox.Show(cont);
}
if (!string.IsNullOrEmpty(cont))
{
var root1 = JsonConvert.DeserializeObject<RootObject>(cont);
int no = 1;
foreach (var provider in root1.Providers)
{
no++;
Button newBtn = new Button()
{
Content = provider.Name.ToString(),
Name = provider.Name.ToString(),
//Width = 88,
//Height = 77,
Visibility = System.Windows.Visibility.Visible,
//Margin = new Thickness(5 + 20, 5, 5, 5),
Background = new SolidColorBrush(Colors.Black),
VerticalAlignment =VerticalAlignment.Center,
Opacity=0.5
};
newBtn.Click += google_click;
System.Windows.Visibility.Visible;
container.Opacity = 0.5;
this.container.Content = newBtn;
}
}
}
Mainpage.xaml:
<Grid xmlns:src="clr-namespace:LRDemo"
Background="White" Margin="10,0,-10,186" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<src:LoginInterfaceControl Grid.Row="0"/>
<!--<src:LoginInterfaceControl Grid.Row="1" Margin="0,15,0,0"/>-->
</Grid>
usercontrol.xaml
<ScrollViewer>
<ContentControl x:Name="container">
<StackPanel x:Name="Panel">
</StackPanel>
</ContentControl>
</ScrollViewer>
there is no need to again create stackpanel and contentcontrol in constructor of usercontrol because they are already there in usercontrol structure.
Contentcontrol can hold content that is assign to it last so I took stackpanel into contentcontol.
usercontrol.xaml.cs
public LoginInterfaceControl()
{
this.InitializeComponent();
abc();
}
public void abc()
{
for (int i = 0; i <= 5; i++)
{
Button newBtn = new Button()
{
Content = "name" + i,
Name = "name" + i,
Background = new SolidColorBrush(Colors.Black),
VerticalAlignment = VerticalAlignment.Center,
Opacity = 0.5
};
newBtn.Click += newBtn_Click;
container.Opacity = 0.5;
this.Panel.Children.Add(newBtn);
}
}
P.S : I do not know your exact need so I took static methods to add buttons.
I 'm creating a Line chart using WPFToolKit.
The chart comes up fine but i want to change the Maximum property of the Y Axis upon button click of a modal window after loading the chart for the first time. And the chart should be refreshed with the updated Y Axis Max value
Below line shows how Chart is defined in xaml.
<DVC:Chart Canvas.Top="80" Canvas.Left="10" Name="mcChart" VerticalAlignment="Stretch"/>
I'm calling below code in windows.xaml.cs constructor and it is setting Y-Axis Max to 200
mcChart.Axes.Add(new LinearAxis()
{
Minimum = 0,
Maximum = YMax > 0 ? YMax : 200,
Orientation = AxisOrientation.Y,
ShowGridLines = true,
});
mcChart.UpdateLayout();
How can i change the Y-Axis Max value from a modal window's button click event and refresh chart to display with new YMax.
I'm not sure if i have to do something with RegisteredListeners.
I'm new to WPF and any help is appreciated!
Please note that i'm looking to achieve this from the C# code behind and not in xaml.
Thanks,
Sujay
If you have access to the chart, you can find the neccessary axis and change the Maximum property without updating layout. Here is an example with a linear Y axis:
var yAxis = this.mcChart.ActualAxes.OfType<LinearAxis>().FirstOrDefault(ax => ax.Orientation == AxisOrientation.Y);
if (yAxis != null)
yAxis.Maximum = 300;
The complete version of this example:
MainWindow.xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Content="Set max value = 300" HorizontalAlignment="Center" Click="Button_Click"/>
<charting:Chart Grid.Row="1" x:Name="mcChart">
<charting:Chart.Series>
<charting:LineSeries ItemsSource="{Binding LineItems}" IndependentValuePath="Date" DependentValuePath="Value"/>
</charting:Chart.Series>
</charting:Chart>
</Grid>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//Add a linear Y axis
int YMax = 150;
mcChart.Axes.Add(new LinearAxis()
{
Minimum = 0,
Maximum = YMax > 0 ? YMax : 200,
Orientation = AxisOrientation.Y,
ShowGridLines = true,
});
//Create and set a view model
var items = Enumerable.Range(0, 50).Select(i => new ChartItemModel { Date = new DateTime(2010, 1, 1).AddDays(i), Value = 30 + i }).ToList();
this.DataContext = new MainViewModel { LineItems = items };
}
//Set Maximum=300
private void Button_Click(object sender, RoutedEventArgs e)
{
var yAxis = this.mcChart.ActualAxes.OfType<LinearAxis>().FirstOrDefault(ax => ax.Orientation == AxisOrientation.Y);
if (yAxis != null)
yAxis.Maximum = 300;
}
}
public class MainViewModel
{
public List<ChartItemModel> LineItems { get; set; }
}
public class ChartItemModel
{
public DateTime Date { get; set; }
public double Value { get; set; }
}