Answered by:
Coverting XML string as DataTemplate using XamlReader.Load() throws exception when adding event to a control in template

Question
-
Hi ,
In my application i Have used a DataTemplate for using in GridView as follows:
DataTemplate myClubDataTemplate = getDataTemplate(186, 123, 80, 13, 8);
DataTemplate getDataTemplate(int width, int height,int imageHeight, int fontSize, int txtBlkMargin)
{
StringBuilder sb = new StringBuilder();
sb.Append("<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">");
sb.Append("<Border Width=\"" + width + "\" Height=\"" + height + "\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Top\" Margin=\"0,0,0,0\" BorderBrush=\"#B2262626\" CornerRadius=\"10,10,10,10\" BorderThickness=\"4\" >");
sb.Append("<StackPanel Orientation=\"Vertical\" Background=\"Transparent\" Margin=\"0,0,0,0\" >");
sb.Append("<Image Source=\"{Binding Path=ImageURL}\" Height=\"" + imageHeight + "\" Stretch=\"Uniform\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Margin=\"0,12,0,0\" ImageFailed=\"image_ImageFailed\" />");
sb.Append("<TextBlock Text=\"{Binding Text}\" FontSize=\"" + fontSize + "\" Foreground=\"White\" HorizontalAlignment=\"Center\" ");
sb.Append("FontWeight=\"Bold\" FontFamily=\"Assets/Fonts/MyriadPro-Regular.otf#Myriad Pro\" Margin=\"0," + txtBlkMargin + ",0,0\" MaxLines=\"2\" TextAlignment=\"Center\" TextWrapping=\"Wrap\" />");
sb.Append("</StackPanel>");
sb.Append("</Border>");
sb.Append("</DataTemplate>");
DataTemplate datatemplate = (DataTemplate)XamlReader.Load(sb.ToString());
return datatemplate;
}But the above method throws exception if i add ImageFailed event to Image control.
How could I solve this issue?
Thanks.
- Edited by PM16 Monday, March 7, 2016 1:12 PM
Monday, March 7, 2016 1:11 PM
Answers
-
Hi dinhg,
As you suggested I added Name Property for a Image control & I could find that Image control by its name.
Next I added a ImageFailed Event to this control. but this event never triggered.Am I missing Anything?
Hi PM16,
To add event handler for the element in your DataTemplate, please use VisualTreeHelper to locate it first, we can handle ContainerContentChanging event and implement this, please set the Name property for your Image control inside DataTemplate:
private void lv_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args) { GridView gv = sender as GridView; //Find the element which Name is img var img = (Image)FrameworkElementExtensions.FindDescendantByName(gv, "img"); if (img != null) { img.ImageFailed += Img_ImageFailed; img.Tapped += Img_Tapped; img.Loaded += Img_Loaded; } } public static class FrameworkElementExtensions { public static FrameworkElement FindDescendantByName(this FrameworkElement element, string name) { if (element == null || string.IsNullOrWhiteSpace(name)) { return null; } if (name.Equals(element.Name, StringComparison.OrdinalIgnoreCase)) { return element; } var childCount = VisualTreeHelper.GetChildrenCount(element); for (int i = 0; i < childCount; i++) { var result = (VisualTreeHelper.GetChild(element, i) as FrameworkElement).FindDescendantByName(name); if (result != null) { return result; } } return null; } }
We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.- Proposed as answer by Xavier Xie-MSFT Wednesday, March 16, 2016 9:38 AM
- Marked as answer by Xavier Xie-MSFT Wednesday, March 23, 2016 2:01 AM
Tuesday, March 15, 2016 7:44 AM -
Hi PM16,
I have checked your code. The main issue was due to the “VariableSizedWrapGrid” control. You could use ItemsWrapGrid to replace it. I have made a code sample for you, please refer to it for details:
<GridView x:Name="display" ItemsSource="{Binding ls}" Foreground="#FFE6D52E" Margin="20,55,20,0" ContainerContentChanging="display_ContainerContentChanging" IsItemClickEnabled="False" ItemTemplate="{Binding mytemplate}" SelectionMode="None" IsDoubleTapEnabled="False" IsHoldingEnabled="False" IsRightTapEnabled="False" IsSwipeEnabled="False" Height="419" > <GridView.ItemsPanel> <ItemsPanelTemplate> <ItemsWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="4" /> </ItemsPanelTemplate> </GridView.ItemsPanel> </GridView>
DataTemplate getDataTemplate(int width, int height, int imageHeight, int fontSize, int txtBlkMargin) { StringBuilder sb = new StringBuilder(); sb.Append("<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">"); sb.Append("<Border >"); sb.Append("<StackPanel >"); sb.Append("<Image Name=\"img\" Source=\"Assets/LockScreenLogo.scale-200.png\" Height=\"" + imageHeight + "\" Stretch=\"Uniform\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Margin=\"0,12,0,0\" />"); sb.Append("</StackPanel>"); sb.Append("</Border>"); sb.Append("</DataTemplate>"); DataTemplate datatemplate = (DataTemplate)XamlReader.Load(sb.ToString()); return datatemplate; } public DataTemplate mytemplate { get; set; } public ObservableCollection<string> ls { get; set; } private async void Page_Loaded(object sender, RoutedEventArgs e) { await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { mytemplate = getDataTemplate(186, 123, 80, 13, 8); ls = new ObservableCollection<string>(); ls.Add("sss"); this.DataContext = this; }); } private void Img_Loaded(object sender, RoutedEventArgs e) { //throw new NotImplementedException(); Debug.WriteLine("Img loaded."); } private void display_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args) { GridView gdv = sender as GridView; System.Diagnostics.Debug.WriteLine(gdv.Items.Count); var img = (Image)FrameworkElementExtensions.FindDescendantByName(display, "img"); if (img != null) { img.Loaded += Img_Loaded; } }
Best Regards,
Xavier Eoro
We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.- Proposed as answer by Xavier Xie-MSFT Monday, March 21, 2016 8:52 AM
- Marked as answer by Xavier Xie-MSFT Wednesday, March 23, 2016 2:01 AM
Thursday, March 17, 2016 9:23 AM
All replies
-
XamlReader.Load not allowed to attach eventHandlers in it. so use this technique to dynamically attach the eventHandlers to it.
1- Write your Xaml string without eventHandlers -But write the Name property of those Controls.
2- Load the string with
XamlReader.Load(str);
3- Then load the content of DataTemplate from it. using
Grid template = ((Grid)(dt.LoadContent()));
Note: here
Grid
is the parent Control inDataTemplate
.4- Find the Control by Name you want to attach the Event Handler.
Button img = (Button)template.FindName("MyButtonInDataTemplate");
Tuesday, March 8, 2016 9:54 AM -
Thank you for kind reply.
Let me try this..
Thanks.
Thursday, March 10, 2016 6:31 AM -
Hi dinhg,
As you suggested I added Name Property for a Image control & I could find that Image control by its name.
Next I added a ImageFailed Event to this control. but this event never triggered.Am I missing Anything?
Thursday, March 10, 2016 8:18 AM -
Hi dinhg,
As you suggested I added Name Property for a Image control & I could find that Image control by its name.
Next I added a ImageFailed Event to this control. but this event never triggered.Am I missing Anything?
Hi PM16,
To add event handler for the element in your DataTemplate, please use VisualTreeHelper to locate it first, we can handle ContainerContentChanging event and implement this, please set the Name property for your Image control inside DataTemplate:
private void lv_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args) { GridView gv = sender as GridView; //Find the element which Name is img var img = (Image)FrameworkElementExtensions.FindDescendantByName(gv, "img"); if (img != null) { img.ImageFailed += Img_ImageFailed; img.Tapped += Img_Tapped; img.Loaded += Img_Loaded; } } public static class FrameworkElementExtensions { public static FrameworkElement FindDescendantByName(this FrameworkElement element, string name) { if (element == null || string.IsNullOrWhiteSpace(name)) { return null; } if (name.Equals(element.Name, StringComparison.OrdinalIgnoreCase)) { return element; } var childCount = VisualTreeHelper.GetChildrenCount(element); for (int i = 0; i < childCount; i++) { var result = (VisualTreeHelper.GetChild(element, i) as FrameworkElement).FindDescendantByName(name); if (result != null) { return result; } } return null; } }
We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.- Proposed as answer by Xavier Xie-MSFT Wednesday, March 16, 2016 9:38 AM
- Marked as answer by Xavier Xie-MSFT Wednesday, March 23, 2016 2:01 AM
Tuesday, March 15, 2016 7:44 AM -
Thanks for your kind reply.
I added the ContainerContentChanging event to my GridView.
but lv_ContainerContentChanging method never triggers.
Can you please check ?
Tuesday, March 15, 2016 2:29 PM -
Hi PM16,
>>” but lv_ContainerContentChanging method never triggers.”
Franklin’s reply was right. I have also made a sample to test, it worked well. So please check your code again. You would need to check if the name of event handler in xaml was consistent with code-behind.
The following is my code:
<GridView x:Name="gv" ContainerContentChanging="gv_ContainerContentChanging"></GridView>
private void gv_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args) { GridView gdv = sender as GridView; System.Diagnostics.Debug.WriteLine(gdv.Items.Count); var img = (Image)FrameworkElementExtensions.FindDescendantByName(gv, "img"); if (img != null) { img.Loaded += Img_Loaded; } }
private void Img_Loaded(object sender, RoutedEventArgs e) { //throw new NotImplementedException(); Debug.WriteLine("Img loaded."); }
Best Regards,
Xavier Eoro
We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.Wednesday, March 16, 2016 8:36 AM -
Hi Xavier,
Please check my following below code.
<GridView x:Name="display" ItemsSource="{Binding}" Foreground="#FFE6D52E" Margin="20,55,20,0" ContainerContentChanging="gv_ContainerContentChanging"
IsItemClickEnabled="False" ItemTemplate="{StaticResource myTemplate}" SelectionMode="None" IsDoubleTapEnabled="False" IsHoldingEnabled="False" IsRightTapEnabled="False" IsSwipeEnabled="False" >
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="4"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
private void gv_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args) { GridView gdv = sender as GridView; System.Diagnostics.Debug.WriteLine(gdv.Items.Count); var img = (Image)FrameworkElementExtensions.FindDescendantByName(gv, "img"); if (img != null) { img.Loaded += Img_Loaded; } }
private void Img_Loaded(object sender, RoutedEventArgs e) { //throw new NotImplementedException(); Debug.WriteLine("Img loaded."); }
I have set breakpoint in gv_ContainerContentChanging. But it never hits. I dont know what i am doing wrongly :(
Thursday, March 17, 2016 7:57 AM -
Hi PM16,
I have checked your code. The main issue was due to the “VariableSizedWrapGrid” control. You could use ItemsWrapGrid to replace it. I have made a code sample for you, please refer to it for details:
<GridView x:Name="display" ItemsSource="{Binding ls}" Foreground="#FFE6D52E" Margin="20,55,20,0" ContainerContentChanging="display_ContainerContentChanging" IsItemClickEnabled="False" ItemTemplate="{Binding mytemplate}" SelectionMode="None" IsDoubleTapEnabled="False" IsHoldingEnabled="False" IsRightTapEnabled="False" IsSwipeEnabled="False" Height="419" > <GridView.ItemsPanel> <ItemsPanelTemplate> <ItemsWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="4" /> </ItemsPanelTemplate> </GridView.ItemsPanel> </GridView>
DataTemplate getDataTemplate(int width, int height, int imageHeight, int fontSize, int txtBlkMargin) { StringBuilder sb = new StringBuilder(); sb.Append("<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">"); sb.Append("<Border >"); sb.Append("<StackPanel >"); sb.Append("<Image Name=\"img\" Source=\"Assets/LockScreenLogo.scale-200.png\" Height=\"" + imageHeight + "\" Stretch=\"Uniform\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Margin=\"0,12,0,0\" />"); sb.Append("</StackPanel>"); sb.Append("</Border>"); sb.Append("</DataTemplate>"); DataTemplate datatemplate = (DataTemplate)XamlReader.Load(sb.ToString()); return datatemplate; } public DataTemplate mytemplate { get; set; } public ObservableCollection<string> ls { get; set; } private async void Page_Loaded(object sender, RoutedEventArgs e) { await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { mytemplate = getDataTemplate(186, 123, 80, 13, 8); ls = new ObservableCollection<string>(); ls.Add("sss"); this.DataContext = this; }); } private void Img_Loaded(object sender, RoutedEventArgs e) { //throw new NotImplementedException(); Debug.WriteLine("Img loaded."); } private void display_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args) { GridView gdv = sender as GridView; System.Diagnostics.Debug.WriteLine(gdv.Items.Count); var img = (Image)FrameworkElementExtensions.FindDescendantByName(display, "img"); if (img != null) { img.Loaded += Img_Loaded; } }
Best Regards,
Xavier Eoro
We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.- Proposed as answer by Xavier Xie-MSFT Monday, March 21, 2016 8:52 AM
- Marked as answer by Xavier Xie-MSFT Wednesday, March 23, 2016 2:01 AM
Thursday, March 17, 2016 9:23 AM -
Thank you Xavier :)
I will try and update you soon.
Thursday, March 17, 2016 10:01 AM -
Hi,
Using ItemsWrapGrid instead of VariableSizedWrapGrid throws exception
Tuesday, March 29, 2016 8:19 AM -
Hi,
Using ItemsWrapGrid instead of VariableSizedWrapGrid throws exception
Hi PM16,
You could post a new thread in this forum about "Using ItemsWrapGrid instead of VariableSizedWrapGrid throws exception". Because this issue was not more related to your original question. If you post several different questions in one thread, it would not be helpful to other developers to find the answer of the similar questions.
In addition, based on your latest reply, you'd better upload your reproducible code sample to OneDrive and post link. I would help you to test in my side.
Best Regards,
Xavier Eoro
We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.Tuesday, March 29, 2016 8:27 AM