My app crashes in the emulator when u load the map and then move the map and zoom in instantly. ive tried many different soulutions i found on the internet as the only error i get is Catastrophic Failure and no further information (no line number or any error information whatsoever)
C# code
public sealed partial class MapView : MvxWindowsPage
{
double lat=0;
double lon=0;
Geolocator gl = new Geolocator();
MapIcon Micon = new MapIcon();
Geopoint blo;
public MapView()
{
this.InitializeComponent();
Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;
GetInitialPosition();
}
private MapViewModel ViewModel
{
get { return DataContext as MapViewModel; }
}
private bool HasViewModel { get { return ViewModel != null; } }
void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
{
e.Handled = true;
Windows.Phone.UI.Input.HardwareButtons.BackPressed -= HardwareButtons_BackPressed;
ViewModel.NavigateFirst();
}
async void GetInitialPosition()
{
gl.DesiredAccuracyInMeters = 500;
gl.DesiredAccuracy = PositionAccuracy.Default;
IAsyncOperation<Geoposition> locationTask = null;
try
{
Geoposition gp = await gl.GetGeopositionAsync(
maximumAge: TimeSpan.FromMinutes(5),
timeout: TimeSpan.FromSeconds(10)
);
//LatitudeTextBlock.Text = geoposition.Coordinate.Latitude.ToString("0.00");
//LongitudeTextBlock.Text = geoposition.Coordinate.Longitude.ToString("0.00");
}
finally
{
DispatcherTimer dt = new DispatcherTimer();
dt.Interval = new TimeSpan(0, 0, 5);
dt.Tick += (sender, e) => ProgBar.Visibility = Visibility.Collapsed;
dt.Tick += (sender, e) => ProgBar.IsEnabled = false;
dt.Start();
}
}
}
}
Xaml:
<views:MvxWindowsPage
xmlns:Maps="using:Windows.UI.Xaml.Controls.Maps"
x:Class="Etgarim.Views.MapView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Etgarim.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:views="using:Cirrious.MvvmCross.WindowsCommon.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Maps:MapControl x:Name="OmNaMap" MapServiceToken="..."/>
<!--Visibility="Visible" Center="{Binding blo}"-->
<ProgressBar x:Name="ProgBar" Height="667"/>
</Grid>
Move the map control and the progress bar so they not over lapping, this should resolve the issue.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="667"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<ProgressBar Grid.Row="0" x:Name="ProgBar" />
<Maps:MapControl Grid.Row="1" x:Name="OmNaMap" MapServiceToken="..."/>
<!--Visibility="Visible" Center="{Binding blo}"-->
</Grid>
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 a window which contains a label and an animated spinner. This window is a kind of splash screen saying "Loading...".
It is a simple basic window:
<Window x:Class="MyWin.SplashScreen"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
<!-- Grid and within the label at row 0, and the spinner at row 1 -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="50*"></RowDefinition>
<RowDefinition Height="20*"></RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">Loading...</Label>
<Grid Name="mySpinner" Grid.Row="1"></Grid>
</Grid>
</Window>
Code behind:
public partial class SplashScreen: Window
{
public SplashScreen()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Forms.Integration.WindowsFormsHost host = new System.Windows.Forms.Integration.WindowsFormsHost();
// Here I instantiate the spinner control and show in UI
UCSpinner myUCSpinner = new UCSpinner();
host.Child = myUCSpinner;
this.mySpinner.Children.Add(host);
}
}
The animated spinner is a control that is instantiated and loaded in the window load event: Window_Loaded
Then from my main wpf window, I have a button. When button is clicked I create a background worker, I start the background worker and after that I call the splash window above indicated. See below.
Main window button:
<Button Grid.Column="1" Width="75" Command="{Binding LaunchOperationCommand}" Content="Calculate" HorizontalAlignment="Right">
</Button>
Code behind:
RelayCommand launchOperationCommand;
public ICommand LaunchOperationCommand
{
get
{
if (launchOperationCommand== null)
launchOperationCommand= new RelayCommand(param => this.DoLongOperation(), param => true);
return launchOperationCommand;
}
}
private void DoLongOperation()
{
BWorker = null;
if (BWorker == null)
{
BWorker = new BackgroundWorker();
BWorker.WorkerReportsProgress = false;
BWorker.WorkerSupportsCancellation = false;
BWorker.DoWork += new DoWorkEventHandler(BWorker_LongOp_DoWork);
BWorker.ProgressChanged += new ProgressChangedEventHandler(BWorker_LongOp_ProgressChanged);
BWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BWorker_LongOp_RunWorkerCompleted);
}
if (BWorker.IsBusy != true)
{
BWorker.RunWorkerAsync();
ShowSplashScreen();
}
}
private System.Windows.Window splashWindow = null;
private void ShowSplashScreen()
{
if (splashWindow == null)
{
splashWindow = new SplashScreen();
}
if (splashWindow .IsVisible == false)
splashWindow .ShowDialog();
}
The problem is the following: The label in the splash screen is displayed but the spinner not.
This is the behaviour copy pasted from wpf-tutorial page:
public class DragBehavior : Behavior<UIElement>
{
private Point elementStartPosition;
private Point mouseStartPosition;
private TranslateTransform transform = new TranslateTransform();
protected override void OnAttached()
{
Window parent = Application.Current.MainWindow;
AssociatedObject.RenderTransform = transform;
AssociatedObject.MouseLeftButtonDown += (sender, e) =>
{
elementStartPosition = AssociatedObject.TranslatePoint(new Point(), parent);
mouseStartPosition = e.GetPosition(parent);
AssociatedObject.CaptureMouse();
};
AssociatedObject.MouseLeftButtonUp += (sender, e) =>
{
AssociatedObject.ReleaseMouseCapture();
};
AssociatedObject.MouseMove += (sender, e) =>
{
Vector diff = e.GetPosition(parent) - mouseStartPosition;
if (AssociatedObject.IsMouseCaptured)
{
transform.X = diff.X;
transform.Y = diff.Y;
}
};
}
}
And this is my test page:
<Page x:Class="WPFApp.Pages.BehaviorPage"
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:WPFApp.Pages"
xmlns:b="clr-namespace:WPFApp.Behaviors"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="BehaviorPage">
<Grid>
<StackPanel >
<Border Background="LightBlue">
<d:Interaction.Behaviors>
<b:DragBehavior/>
</d:Interaction.Behaviors>
<TextBlock Text="Drag me around!" Width="110" FontSize="14"/>
</Border>
</StackPanel>
</Grid>
</Page>
When i want to debug 'OnAttached()' is never hit/called. So Drag&Drop also doesn't work.
Blend was included in VisualStudio2105 and comes with the interactivity dll. If you use the path: xmlns:d="http://schemas.microsoft.com/expression/2010/interactivity" instead of xmlns:d="http://schemas.microsoft.com/expression/blend/2008" the OnAttached method gets called correctly.
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. :)
I have a WPF app that I'm testing which loads a XML and visualizes it in a usercontrol. Now the issue I'm having is that every time I load my user control the HorizontalAlignment is okay, but the VerticalAlignment doesn't adept to the height size of the usercontrol.
Anyone has an idea how to solve this?
MainWindow.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:UserControls="clr-namespace:RackBuildingTesT.UserControls" x:Class="RackBuildingTesT.MainWindow"
Title="MainWindow" Height="578" Width="758" SizeChanged="Window_SizeChanged_1">
<Grid>
<DockPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Border DockPanel.Dock="Top" BorderBrush="Black" BorderThickness="1">
<Grid>
<Label Content="Welke rack laden" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<ComboBox x:Name="RackChooser" HorizontalAlignment="Left" Margin="100,0,0,0" VerticalAlignment="Top" Width="120" SelectionChanged="RackChooser_SelectionChanged"/>
</Grid>
</Border>
<Border DockPanel.Dock="Top" BorderBrush="Black" BorderThickness="1">
<Grid x:Name="RackGrid" Margin="0,0,0,0">
</Grid>
</Border>
</DockPanel>
</Grid>
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
LoadRackCombo();
}
private void LoadRackCombo()
{
var files = Directory.GetFiles(Properties.Settings.Default.FilePathXMLRack);
foreach (var item in files)
{
RackChooser.Items.Add(item);
}
}
private void RackChooser_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.RackGrid.Children.Clear();
this.Cursor = Cursors.Wait;
if (RackChooser.SelectedIndex == -1)
MessageBox.Show("Select a rack");
else
{
string rackFile = Convert.ToString(RackChooser.Items[RackChooser.SelectedIndex]);
UserControls.RackBuilder r = new UserControls.RackBuilder();
RackGrid.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
RackGrid.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
r.Width = RackGrid.Width;
r.Height = RackGrid.Height;
var _r = TRack.CreateFromXMLFile(rackFile, null);
r.set_Rack(_r);
RackGrid.Children.Add(r);
}
this.Cursor = Cursors.Arrow;
}
private void Window_SizeChanged_1(object sender, SizeChangedEventArgs e)
{
RackGrid.Width = this.Width;
RackGrid.Height = this.Height;
}
RackBuilder.xaml.cs (xaml page is standard WPF usercontrol)
public RackBuilder()
{
InitializeComponent();
}
public TRack fRack { get; set; }
public void set_Rack(TRack value)
{
this.fRack = value;
this.InvalidateVisual();
}
protected override void OnRender(DrawingContext drawingContext)
{
if (this.fRack != null)
{
var xScale = this.Width / this.fRack.Size.Width;
var yScale = this.Height / this.fRack.Size.Height;
var smallest = 0.0;
if (xScale < yScale)
smallest = xScale;
else
smallest = yScale;
foreach (var hole in this.fRack.HolePositions)
{
drawingContext.DrawEllipse(Brushes.Aquamarine, null, new Point(hole.Position.X * xScale, hole.Position.Y * yScale),
hole.Diameter * smallest * 0.5, hole.Diameter * smallest * 0.5);
}
}
}
Result
Instead of adding your Control to a Grid, use the ContentControl and add it to its Content-Property.
It also stretches its child automatically.
I fixed it with putting the MainWindow SizeToContent to WidthAndHeight.