UWP app, crash on this.Frame.Navigate - c#

I have a UWP app, with two Pages: MainPage and EventPage. On both of these there is a splitView, and at the top of this a GridView with two buttons - one to navigate to MainPage, and one to navigate to EventPage. The XAML for the buttons looks like this:
<Button Content="Browse by system"
HorizontalAlignment="Center"
Margin="0,0,0,0"
VerticalAlignment="Top"
Width="250"
Click="SystemButtonClick"/>
However, when i press the "Browse by system" button, the app crashes. Here is the constructor for the page:
public EventPage()
{
this.InitializeComponent();
var systemList = SystemClass.GetSystems();
systemList.Sort();
Systems = new ObservableCollection<string> (systemList);
}
It passes the constructor fine, and instead crashes when exiting the eventhandler for the button click:
private void SystemButtonClick(object sender, RoutedEventArgs e)
{
this.Frame.Navigate(typeof(EventPage));
}
I've modeled this after the Peer-to-peer navigation tutorial from microsoft, and can't find any significant differences. The only similar issue I could find here was this, but that seemed to be due to the Template10 package which I'm not using.
When the crash does occur, it goes to the App.g.i.cs file and complains that the debugger isn't configured to debug this unhandled exception.
Does anyone have any idea why this might be happening?
EDIT: To add, if I click the button to move to the current page, it reloads fine. I also just tried starting the program to the EventPage, which also prompted a crash.
EDIT2: After some further testing, it seems I've located the source of the crash, though I don't understand it.
At the beginning of my EventPage class, I have a few variables:
public sealed partial class EventPage : Page
{
private ObservableCollection<EventBin> EventCollection;
private ObservableCollection<String> Systems;
public EventPage()
{
this.InitializeComponent();
Systems = SystemClass.GetSystems();
}
It seems that the crass occurs when I assign the Systems variable. This doesn't occur with my identical operation for the other page, with a different variable. The only difference being that in the MainPage, it's an ObservableCollection of a custom class rather than of strings.
If I re-initialize the System variable like this:
var Systems = SystemClass.GetSystems();
It runs, but doesn't connect to my bindings in the XAML.

So, it turned out that the issue was that I had bound a custom type to the list in my data template, and then tried feeding it plain strings.
<DataTemplate x:Key="System_DefaultItemTemplate"
x:DataType="local:SystemClass">
<StackPanel>
<TextBlock Text="{x:Bind Name}"/>
<TextBlock Text="{x:Bind Site}"/>
</StackPanel>
</DataTemplate>
Since the strings obviously didn't have any Name or Site properties, it crashed.

Related

How to call User Control creating just one instance using MVVM in WPF?

I'm working in a WPF project and a newer on this, I'm using the MVVM patter in my project.
I have a MainWindows which calls User Controls and I have a MainWindowsModel which helps me to Create an instance, save them in a variable for opening in my MainWindows...
My problems comes here, when I use the menu of my window (look the photos below) the User Control is refresing like creating a new instance...
I create a repository where i simulate my problem, try to write in the textBox and then click on other bottom Menu, Then return to the before Button you won't be able to watch the message you wrote there.
Hope some helps me with this because i have no idea how to manage User Control just creating one Instance and don't save data when i change between UserControls.
Look at the image if I didn't explain well
The repo for this question with interface in the photo:
Click on here to open the Repository
I was looking for examples on other post but i didn't fine a way to make my information stays on my UserControl.
I will be active for this question...
The information is not supposed to "stay in the UserControl.
You should bind the TextBox to a property of the view model and store the string value there. It won't/shouldn't be stored in the view that gets unloaded.
HomeView.xaml:
<TextBox Text="{Binding Text}"
FontSize="20"
Margin="10,10,0,0"
Foreground="Green"
Width="300"
Height="50"/>
HomeViewModel:
public class HomeViewModel : ViewModelBase
{
private string _text = "Write something";
public string Text
{
get { return _text; }
set { _text = value; OnPropertyChanged(nameof(Text)); }
}
}

WPF WebView2 Initialization in viewmodel never returns

In my wpf application i try to show a webView2 for a login, even though when i navigate to the view and start the initialization nothing happens. I've tried many options and solutions i found in the internet and that worked for others but nothing helped.
The Code:
private WebView2 m_webView21;
public WebView2 WebView21 { get => m_webView21; set => SetProperty(ref m_webView21, value); }
protected async Task<WebView2> CreateBrowserAndLoadUrlAsync(string url)
{
webView21 = new WebView2();
webView21.CoreWebView2InitializationCompleted += WebView21_CoreWebView2InitializationCompleted;
Debug.WriteLine("InitializeAsync");
await webView21.EnsureCoreWebView2Async();
Debug.WriteLine("WebView2 Runtime version: " + webView21.CoreWebView2.Environment.BrowserVersionString);
SetBrowserHostVisibility(Visibility.Visible);
if (webView21 != null && webView21.CoreWebView2 != null)
{
webView21.CoreWebView2.Navigate(url);
}
return webView21;
}
private void WebView21_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
{
webView21.Loaded += Browser_FrameLoadEnd;
webView21.Initialized += Browser_InitializedChanged;
}
--Xaml Code--
<Grid Background="Transparent">
<wv2:WebView2 Visibility="Visible" Source="{Binding WebView21.Source.AbsoluteUri, Mode=OneWay}"/>
</Grid>
This is the first thing i'm calling in my viewmodel from the OnNavigatedTo(). Everything works as it should untig it comes to the EnsureCoreWebViewAsync() - from this function it never returns - just nothing happens.
When i do not initialize the webview2 and just set the source to the uri everything works fine aswell. But no events or anything get fired (e.g. NavigationCompleted, SourceChanged, etc.) and i need those events ofc.
I installed the correct runtime i also installed the WebView2 Plugin of course. Also tried different enviroments nothing helped.
So the actual question is, is it even possible to initialize the WebView2 from the Viewmodel?
I found the solution. I had to use a placeholder in my xaml which later init's the webView2 in my Viewmodel.
Just change the xaml code from the question with this and it should work fine
<ContentControl Content="{Binding WebView21, Mode=OneWay}" />
Thanks for all the helpful comments :))

Use SendKeys in a UserControl

I want to use the C# System.Windows.Forms.SendKeys.SendWait() Method to send Keystrokes from an OnScreenKeyboard to a Textbox. Since I may use this OnScreenKeyboard at other places too I created a UserControl with View (for the Design of the Keyboard) and Viewmodel (basically for calling the Sendkeys.SendWait() Method) in an extra project.
Within this project I created a MainView where I included the UserControl via a ContentControl as you can see in the Code below. CurrentPage basically refers to the Viewmodel of the Keyboard.
<Window.Resources>
<DataTemplate DataType="{x:Type viewModel:KeyboardViewmodel}">
<view:KeyboardView/>
</DataTemplate>
</Window.Resources>
<Grid>
<Border Background="White">
<HeaderedContentControl Content="{Binding Path=CurrentPage}"/>
</Border>
<TextBox Width="120"/>
</Grid>
I now have the OnScreenKeyboard and a Textbox in my Window. Clicking into the Textbox and pressing buttons of my OnScreenKeyboard will result in text appearing in my Textbox. All Controls within the KeyboardView are set to avoid getting focus. This is necessary to maintain focus on the Textbox.
The Buttons in the KeyboardView all bind to the Command ClickCommandin my KeyboardViewmodel. Here is the code of the KeyboardViewmodel:
public class KeyboardViewmodel : BaseModel
{
public BaseCommand ClickCommand { get; set; }
public KeyboardViewmodel()
{
ClickCommand = new BaseCommand(PressAndRelease);
}
public void PressAndRelease(object key)
{
if (((string)key).Length <= 1)
SendKeys.SendWait((string)key);
else
SendKeys.SendWait("{" + (string)key + "}");
}
}
Now I did create a NuGet Package with these Files and imported them to the project where I want to use my OnScreenKeyboard.
I did do basically the same as when I tested the OnScreenKeyboard before.
But let me explain the structure of the project a little more:
I have a MainView + MainViewmodel. The MainViewmodel manages the navigation between available pages. To show these pages I have - as in the short example before - a ContentControl whose content is bound to a CurrentPage Property. The MainViewis a normal Window, all other Views are UserControls.
In one of these pages I need an OnScreenKeyboard (DetailsView + DetailsViewmodel). So it seemed logical to me to use another ContentControl within the DetailsView:
<Border Grid.Column="0" Grid.Row="4" Grid.ColumnSpan="3" Height="Auto" Width="Auto">
<ContentControl Content="{Binding Path=OnScreenKeyboard}"/>
</Border>
I create the KeyboardViewmodel in the constructor of the DetailsViewmodel. The constructor of the DetailsViewmodel is called in the MainViewmodel at startup.
So now everything works out fine so far, the OnScreenKeyboard is shown on the correct page in the correct place. If I click a button of the OnScreenKeyboard the proper bound command is called and the SendKeys.SendWait() Method is called.
But no text appears in the TextBox. I have a very bad understanding of the SendKeys.SendAwait() Method. Also, the MSDN Documentation seems to be not very exhaustive on this topic.
It states: "Sends the given keys to the active application, and then waits for the messages to be processed."
Now. The Active / Focused Application is my Application. So my guess is that the KeyStrokes should be processed by my Textbox.
My Questions:
Any guesses how to debug the 'SenWait()' Method further e.g. track where the strokes are really sent to or something like that?
Is this the correct way for sending KeyStrokes to an active Application? It seems like SendKeys comes from Windows Forms, I use WPF.
Should I just pass my Textbox as reference to the OnScreenKeyboard and write directly to the referenced Textbox? This would make me much less flexible in regards of reusability.
Update:
As pointed out in the comments this could probably be a duplicate question.
I am well aware of the various different solutions and have already considerd them:
http://wpfkb.codeplex.com/
http://www.codeproject.com/Articles/32568/A-Touch-Screen-Keyboard-Control-in-WPF
http://www.codeproject.com/Articles/145579/A-Software-Virtual-Keyboard-for-Your-WPF-Apps
But as one may understand these projects are looking all way too powerfull for my simple needs.
Here a screenshot to provide a better understanding of my needs:
It is really as simple as that. 4 rows of buttons that will never change, no other controls / functionality than sending the CommandParameter of the pressed button to the Textbox / Active Form.
Researching on that specific problem hasn't shown any problems like that. In most other SO Questions the problem is to send Data to another Window, not to send Data WITHIN the current Window.
So I don't consider this question as duplicate.

Invalid image path gets hidden

I spent far too long today trying to figure out why my WPF application seemed to be taking so long to load windows that previously loaded much quicker. It turned out that the cause of the problem was an image control with an invalid source uri (for whatever reason, we hadn't noticed the images weren't being rendered).
Whilst the actual code was a lot more involved, (the images spanned many dlls) I can easily reproduce the problem below.
public partial class MainWindow : Window
{
public List<object> Items { get; private set; }
public MainWindow()
{
Items = Enumerable.Repeat(new object(), 250).ToList();
DataContext = this;
InitializeComponent();
}
}
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="icon.png" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
When you replace the source with something that doesn't exist, instead of getting an exception or at least something in the output window all you get is a very long delay before the application starts. Clearly, in this simple example it is easy to see what's wrong, but not so in a large project.
I don't want to get caught by this again, is there anyway to catch these kind of errors? why am I not seeing anything in the output window of a debug build?
EDIT : So it turns out I can do something like this
public partial class App : Application
{
public App()
{
EventManager.RegisterClassHandler(typeof(Image), Image.ImageFailedEvent,
new EventHandler<ExceptionRoutedEventArgs>(OnImageFailed));
}
void OnImageFailed(object sender, ExceptionRoutedEventArgs e)
{
throw new Exception("Image Failed! : " + e.ErrorException.Message, e.ErrorException);
}
}
I'm not overly happy with this though as there could be other controls that may suffer from the same issue and will go undetected until a handler like above is added.

WPF Combobox deriving from derived doesn't work

HOPEFULLY, someone strong in WPF knows what's going on... The scenario I've sampled below is also applicable to others too, like textbox, command buttons, etc...
I'm playing with creating custom user controls... Ex: working with a simple Combobox. In one project class library LibA I've created some samples derived from... ex: TextBox, ComboBox, Window, etc. A second library LibB I'm creating another class derived from ex: Combobox in LibA... Otherwise, no problem.... done similar thing in C# WinForms with no problems.
Now, the problem, I drag the control (from LibB) onto the first "Window" (native so no derivation issues) of the app, save and run. The derived library doesn't even hit its constructor which I just put a simple command just test it was getting created properly worked or not, but its not... In the XAML of the form, it is properly referencing both namespace projects, so I know that appears correct.
So, I then created a derived combobox in the same original LibA, put that on the form, and IT properly went into the constructor.
Here's a snippet of what I have going on.
namespace LibA
{
public class MyCombo1 : ComboBox
{
public MyCombo1()
{ ToolTip = "this is my base declaration"; }
}
public class MyCombo1b : MyCombo1
{
public MyCombo1b() : base()
{ ToolTip = "this constructor IS reached"; }
}
}
In a separate project (library),
using FirstLibraryThatHas_MyCombo1
namespace LibB
{
public class OtherLibCombobox : MyCombo1
{
public OtherLibCombobox() : base()
{ ToolTip = "this version is NOT being recognized in the window"; }
}
}
So, neither of these are visually designed, they are all in code only... In addition, I've done it with the TextBox control too, same results... It doesn't stop in the debugger... Any ideas?
Although I've changed actual names from sample, here's a brand new window, one with original class declaration AND one with the DERIVED version.. Here's a full XAML test window
<Window x:Class="MyProject.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="300" Width="300"
xmlns:my="clr-namespace:WPFGUI;assembly=WPFGUI"
xmlns:my1="clr-namespace:DerivedControls;assembly=DerivedControls">
<Grid>
<my:MyComboBoxClass
Name="MyComboBoxInWindow"
HorizontalAlignment="Left"
Height="23"
Width="120" />
<my1:cboDerivedComboClass
Name="cboDerivedComboInWindow"
Height="23"
HorizontalAlignment="Left"
Width="120" />
</Grid>
</Window>
Isn't this making a circular reference?
You call MyDerivedControl that is in another assembly, and DerivedControl needs the primary assembly
because it inherits a type you defined there.
And then, you try to display it in a window from the primary assembly?
Try to clean and rebuild your project.
I've tried and failed to reproduce the problem. I think you have a different problem, though. If you use the xaml above - the number two combobox will completely cover the first - thus you will not be able to get the tooltip...
Also, check that all assemblies target the same framework version.

Categories