XamlParerException: while trying to link text to Xaml page - xaml

(Windows Phone Project ) I am trying to create a scenario were a user would click a text and a xaml page would be displayed be display.
The text is called "Terms and Condition".
Event code for the text component
private void MouseEnter_Agent(object sender, System.Windows.Input.KeyEventArgs e)
{
this.NavigationService.Navigate(new Uri("/AgentTerms.xaml", UriKind.Relative));
}
The Xaml interface code
<TextBlock TextWrapping="Wrap" Height="30" Foreground="Red" MouseEnter="MouseEnter_Agent">
<Underline>
<Run Text="Read JizAgent Terms and Conditions"/>
</Underline>
<LineBreak/>
<Run/>
</TextBlock>
I get the error when I click the text - XamlParerException

You're using the wrong EventArgs class in your event handler's signature. You should be using MouseEventArgs. Take this basic example:
<Window x:Class="MouseEventArgs.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MouseEventArgs" Height="300" Width="300">
<Grid x:Name="LayoutRoot"
Background="Green"
MouseEnter="Grid_MouseEnter" />
</Window>
Code behind:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
namespace MouseEventArgs
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
void Grid_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
LayoutRoot.Background = new SolidColorBrush(Colors.Red);
}
}
If this fails then it would have to be an issue with the markup in AgentTerms.xaml.

void MouseEnter_Agent(object sender, System.Windows.Input.KeyEventArgs e)
The signature of the handler is wrong. Replace it with:
void MouseEnter_Agent(object sender, System.Windows.Input.MouseEventArgs e)

Related

How to make GradientStopCollection Observable?

i have run into a problem where i want to show a list of gradient stops in a listbox. The problem is that putting the gradientstops in a collection of type ObservableCollection works, but using a GradientStopCollection does not.
When i Use GradientStopCollection, the items that are in the list before the window is initialized are shown, but when a button is pressed to add a third item, the UI is not updated.
Calling OnPropertyChanged does not result in the UI being updated. I have made a small example to try to reproduce the problem.
So how can get the window to correctly update even when i use a gradientstop collection?
using System.Windows;
using System.Windows.Media;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
DataContext = new ViewModel();
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
ViewModel vm = (DataContext as ViewModel);
vm.Collection.Add(new GradientStop(Colors.Red, 0.5));
//This line has no effect:
vm.OnPropertyChanged("Collection");
}
}
}
Viewmodel:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
namespace WpfApp1
{
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public GradientStopCollection Collection
{
get
{
return collection;
}
set
{
collection = value;
}
}
//Replacing GradientStopCollection
// with ObservableCollection<GradientStop> makes it work
GradientStopCollection collection;
public ViewModel()
{
GradientStop a = new GradientStop(Colors.Green, 0);
GradientStop b = new GradientStop(Colors.Yellow, 1.0);
collection = new GradientStopCollection() { a, b } ;
OnPropertyChanged("Collection");
}
public void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
handler?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
public class Converter : IValueConverter
{
public object Convert(object value, Type targettype, object parameter, CultureInfo cultureInfo)
{
if (value is Color color)
return new SolidColorBrush(color);
return Binding.DoNothing;
}
public object ConvertBack(object value, Type targettype, object parameter, CultureInfo cultureInfo)
{
throw new NotImplementedException();
}
}
}
And finally the xaml:
<Grid>
<Grid.Resources>
<local:Converter x:Key="ColorConverter"/>
<DataTemplate DataType="{x:Type GradientStop}">
<TextBlock
Width="50"
Background="{Binding Color, Converter={StaticResource ColorConverter}}"
Text="block"
/>
</DataTemplate>
</Grid.Resources>
<ListBox
x:Name="GradientListBox"
Width="72"
Height="92"
ItemsSource="{Binding Collection}" />
<Button Content="Button" HorizontalAlignment="Left" Margin="169,264,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
I don't think that there is any easy way around this problem.
You could create your own collection class, inheriting from GradientStopCollection and implementing the interface INotifyCollectionChanged, effectively making an ObservableGradientStopCollection.
You can probably find an implementation of INotifyCollectionChanged as an excmple.
It might be easier, just to keep two collections, although it seems like bad style.

Hyperlink navigateuri to Childwindow

hyperlink opens childwindow silverlight
How can I open a childwindow using an hyperlink navigateuri in silverlight?
<HyperlinkButton x:Name="Login" Style="{StaticResource LinkStyle}"
NavigateUri="[ChildWindow]" TargetName="ContentFrame" Content="login"/>
Thanks in advance
Why do you want to use the NavigateUri?
You can just use the Click event, like you would do with an ordinary Button.
<HyperlinkButton
x:Name="Login"
Content="login"
Click="OpenChildWindow"
Style="{StaticResource LinkStyle}"/>
and in codebehind:
public class MyView : UserControl
{
public MyView()
{
InitializeComponent();
}
public void OpenChildWindow(object sender, EventArgs args)
{ ... }
}

How can I save coordinates of mouse click in Blend for Visual Studio?

I want to prototype an interface for touchscreen so that I can record every mouse click during the user test.
I suceeded in making storyboard, but failed in logging mouse click.
I looked up other questions -
How do I get the current mouse screen coordinates in WPF?, How do I get the current mouse screen coordinates in WPF? -
but couldn't understand how to apply those codes to .xaml or code-behind file(I got error message every trial.)
If I want to record where testers click on the canvas, how can I track coordinates and export logs to other file format?
A really simple example,
This will record every position the user has clicked and when :
<Window x:Class="WpfApplication6.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350"
MouseDown="MainWindow_OnMouseDown">
<Grid>
<Button Width="75"
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="Button_Click"
Content="_Show log" />
</Grid>
</Window>
Code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Input;
namespace WpfApplication6
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private readonly List<Tuple<DateTime, Point>> _list;
public MainWindow()
{
InitializeComponent();
_list = new List<Tuple<DateTime, Point>>();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
IEnumerable<string> #select = _list.Select(s => string.Format("{0} {1}", s.Item1.TimeOfDay, s.Item2));
string #join = string.Join(Environment.NewLine, #select);
MessageBox.Show(join);
}
private void MainWindow_OnMouseDown(object sender, MouseButtonEventArgs e)
{
Point position = e.GetPosition((IInputElement) sender);
var tuple = new Tuple<DateTime, Point>(DateTime.Now, position);
_list.Add(tuple);
}
}
}

Windows 8.1: Behaviors on Flyouts don't Work

I am developing a windows 8.1 app using VS 2013 and MVVM Light.
The following code shows the behavior in a flyout within an appbar:
<AppBarButton.Flyout>
<Flyout x:Name="FlyoutCalculator"
Placement="Top"
FlyoutPresenterStyle="{StaticResource FlyoutPresenterBaseStyle}">
<uc:Calculator ApplyCommand="{Binding CancelCommand}"
CancelCommand="{Binding CancelCommand}"
Available="{Binding AvailableCounter, Mode=OneWay}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"/>
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Opening">
<core:InvokeCommandAction Command="{Binding ShowCurrentCostsCommand}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Flyout>
</AppBarButton.Flyout>
Unfortunately I get an exception while compiling the app:
WinRT-Informationen: Cannot add instance of type Microsoft.Xaml.Interactions.Core.EventTriggerBehavior to a collection of type Microsoft.Xaml.Interactivity.BehaviorCollection
Other Behaviors in the View do work, does someone know a solution to this?
Extremely late answer here, but I had the same issue and came up with a solution after finding this post.
I just created a custom behavior specifically for flyouts, used like this. OpenActions will execute when the flyout is opened, and CloseActions will execute when the flyout closes. In this case, I wanted the bottom app bar to not be visible when the flyout was open.
<Flyout Placement="Full">
<i:Interaction.Behaviors>
<behaviors:FlyoutBehavior>
<behaviors:FlyoutBehavior.OpenActions>
<core:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" TargetObject="{Binding ElementName=CommandBar}" />
</behaviors:FlyoutBehavior.OpenActions>
<behaviors:FlyoutBehavior.CloseActions>
<core:ChangePropertyAction PropertyName="Visibility" Value="Visible" TargetObject="{Binding ElementName=CommandBar}" />
</behaviors:FlyoutBehavior.CloseActions>
</behaviors:FlyoutBehavior>
</i:Interaction.Behaviors>
<Grid>
...
</Grid>
</Flyout>
Code is here:
class FlyoutBehavior : DependencyObject, IBehavior
{
public DependencyObject AssociatedObject { get; private set; }
public void Attach(Windows.UI.Xaml.DependencyObject associatedObject)
{
var flyout = associatedObject as FlyoutBase;
if (flyout == null)
throw new ArgumentException("FlyoutBehavior can be attached only to FlyoutBase");
AssociatedObject = associatedObject;
flyout.Opened += FlyoutOpened;
flyout.Closed += FlyoutClosed;
}
public void Detach()
{
var flyout = AssociatedObject as FlyoutBase;
if (flyout != null)
{
flyout.Opened -= FlyoutOpened;
flyout.Closed -= FlyoutClosed;
}
}
public static readonly DependencyProperty OpenActionsProperty =
DependencyProperty.Register("OpenActions", typeof(ActionCollection), typeof(FlyoutBehavior), new PropertyMetadata(null));
public ActionCollection OpenActions
{
get { return GetValue(OpenActionsProperty) as ActionCollection; }
set { SetValue(OpenActionsProperty, value); }
}
public static readonly DependencyProperty CloseActionsProperty =
DependencyProperty.Register("CloseActions", typeof(ActionCollection), typeof(FlyoutBehavior), new PropertyMetadata(null));
public ActionCollection CloseActions
{
get { return GetValue(CloseActionsProperty) as ActionCollection; }
set { SetValue(CloseActionsProperty, value); }
}
private void FlyoutOpened(object sender, object e)
{
foreach (IAction action in OpenActions)
{
action.Execute(AssociatedObject, null);
}
}
private void FlyoutClosed(object sender, object e)
{
foreach (IAction action in CloseActions)
{
action.Execute(AssociatedObject, null);
}
}
public FlyoutBehavior()
{
OpenActions = new ActionCollection();
CloseActions = new ActionCollection();
}
}
I do not have a solution but:
I'm not using Flyouts in my Windows 8.1 App, I'm using a UserControl on which I have added a EventTriggerBehavior as you did. And I get exactly the same Errormessage from VisualStudio at runtime.
As I am using a RoutedEventHandler this could cause the Problem as you use
EventHandler<object> Opening
as the Trigger for the Behavior. But that is just an idea of what is the problem.
For me I have found an answer:
I have changed the Type of my RoutedEventHandler to be just a normal EventHandler. And the Method inside the CodeBehind which triggers the RoutedEventHandler is invoked with only the sender, because I dont know how to convert RoutedEventArgs into EventArgs, but as long as I dont need the EventArgs it's not a problem.
You could also make a workaround by creating a UserControl with a Flyout Control and make the Opening Event public to the Page where you use it. Then you can add the EventTriggerBehavior to the UserControl and connect it to your custom Opening Event and you should get the expected behavior.

PropertyChanged always null

This is my MainPage.xaml :-
<UserControl x:Class="SilverlightPlainWCF.MainPage"
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"
d:DesignHeight="450" d:DesignWidth="800" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" xmlns:my="clr-namespace:SilverlightPlainWCF.CustomersServiceRef" Loaded="UserControl_Loaded">
<UserControl.Resources>
<CollectionViewSource x:Key="customerViewSource" d:DesignSource="{d:DesignInstance my:Customer, CreateList=True}" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<sdk:DataGrid AutoGenerateColumns="False" Height="426" HorizontalAlignment="Left" ItemsSource="{Binding}" Margin="12,12,0,0" Name="customerDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Top" Width="776">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn x:Name="addressColumn" Binding="{Binding Path=Address}" Header="Address" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="cityColumn" Binding="{Binding Path=City}" Header="City" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="companyNameColumn" Binding="{Binding Path=CompanyName}" Header="Company Name" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="contactNameColumn" Binding="{Binding Path=ContactName}" Header="Contact Name" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="contactTitleColumn" Binding="{Binding Path=ContactTitle}" Header="Contact Title" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="countryColumn" Binding="{Binding Path=Country}" Header="Country" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="customerIDColumn" Binding="{Binding Path=CustomerID}" Header="Customer ID" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="faxColumn" Binding="{Binding Path=Fax}" Header="Fax" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="phoneColumn" Binding="{Binding Path=Phone}" Header="Phone" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="postalCodeColumn" Binding="{Binding Path=PostalCode}" Header="Postal Code" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="regionColumn" Binding="{Binding Path=Region}" Header="Region" Width="SizeToHeader" />
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>
</UserControl>
This is my MainPage.xaml.cs :-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using SilverlightPlainWCF.CustomersServiceRef;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace SilverlightPlainWCF
{
public partial class MainPage : UserControl, INotifyPropertyChanged
{
public MainPage()
{
InitializeComponent();
this.DataContext = Customers;
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
public ObservableCollection<Customer> customers;
public ObservableCollection<Customer> Customers
{
get { return customers; }
set
{
customers = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Customers"));
}
}
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
CustomersServiceClient objCustomersServiceClient = new CustomersServiceClient();
objCustomersServiceClient.GetAllCustomersCompleted += (s, res) =>
{
if (res.Error == null)
{
Customers = new ObservableCollection<Customer>(res.Result);
}
else
{
MessageBox.Show(res.Error.Message);
}
};
objCustomersServiceClient.GetAllCustomersAsync();
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
// Do not load your data at design time.
// if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
// {
// //Load your data here and assign the result to the CollectionViewSource.
// System.Windows.Data.CollectionViewSource myCollectionViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["Resource Key for CollectionViewSource"];
// myCollectionViewSource.Source = your data
// }
// Do not load your data at design time.
// if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
// {
// //Load your data here and assign the result to the CollectionViewSource.
// System.Windows.Data.CollectionViewSource myCollectionViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["Resource Key for CollectionViewSource"];
// myCollectionViewSource.Source = your data
// }
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
If i just move the line :-
this.DataContext = Customers;
from constructor to here :-
if (res.Error == null)
{
Customers = new ObservableCollection<Customer>(res.Result);
this.DataContext = Customers;
}
It works fine and I get all the data. What might be the problem?
The reason that it didn't work when you put it in the constructor is that there is not yet any value in the customers field at that moment.
You will only get the value when MainPage_Loaded is triggered, which will not happen because of the following line in your XAML:
Loaded="UserControl_Loaded"
That will execute UserControl_Loaded and not MainPage_Loaded. What you can do is call MainPage_Loaded from UserControl_Loaded, which probably is not what you intend to do. So in that case you should change your XAML instead to:
Loaded="MainPage_Loaded"
And you can delete UserControl_Loaded altogether since you are not using it anymore.
And as for the assigning of the result to the DataGrid, you can actually do it directly by assigning the result straight to the DataContext instead of going through the Customers property.
But if you insist to assign it to the Customers property and have the DataGrid updated accordingly, then the next easiest solution would be to include the following line somewhere in your Customers set method:
DataContext = value;
If you really, really insist that the DataGrid should update itself when the PropertyChanged event is triggered, without having you to code the DataContext = Customers row, then what you want is data binding. By binding the DataContext property to your Customers property, then the DataGrid will be updated when it receive the PropertyChanged event.
To declare the data binding in XAML, you would need to assign a name to your UserControl tag. Then you would assign the binding to the DataContext, something along this line:
DataContext="{Binding Path=Customers, ElementName=theUserControlName}"
And if I were you, instead of having to implement the INotifyPropertyChanged interface, I would instead use Dependency Properties instead. Converting your example to use Dependency Property, I would have:
public static DependencyProperty CustomersProperty =
DependencyProperty.Register("Customers", typeof(ObservableCollection<Customer>), typeof(MainPage), null);
public ObservableCollection<Customer> Customers
{
get { return (ObservableCollection<Customer>) GetValue(CustomersProperty); }
set { SetValue(CustomersProperty, value); }
}
Just that, the property change notification will be handled by the framework.
I believe the problem is that in the constructor you do not have this line:
Customers = new ObservableCollection<Customer>(res.Result);
before you attempt to set the DataContext to that value.