A Microsoft.UI.Xaml.Markup.XamlParseException occurs when rendering many CheckBoxes - xaml

I'm working on WinUI3. An UnhandledException occurs when the code below is executed and CheckBoxes are rendered.
public List<int> Collection { get; set; }
public ViewModelConstructor()
{
Collection = new();
for (int i = 0; i < 100; i++)
{
Collection.Add(0);
}
}
<ItemsRepeater ItemsSource="{x:Bind ViewModel.Collection}">
<DataTemplate x:DataType="x:Int32">
<StackPanel Orientation="Horizontal">
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
<CheckBox/>
</StackPanel>
</DataTemplate>
</ItemsRepeater>
UnhandledException += (sender, e) =>
{
if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
};
// e.Message: "Failed to assign to property 'Microsoft.UI.Xaml.Controls.AnimatedIcon.Source'. [Line: 0 Position: 0]"
// e.Exception.Message: "XAML parsing failed."
// typeof(e.Exception): Microsoft.UI.Xaml.Markup.XamlParseException
result
exception
It works normally when modified like the code below.
public ViewModelConstructor()
{
Collection = new();
for (int i = 0; i < 30; i++)
{
Collection.Add(0);
}
}
Alternatively, changing CheckBox to Button will work normally.
<ItemsRepeater ItemsSource="{x:Bind ViewModel.Collection}">
<DataTemplate x:DataType="x:Int32">
<StackPanel Orientation="Horizontal">
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
<Button/>
</StackPanel>
</DataTemplate>
</ItemsRepeater>
I've tried many things and guessed it, it seems to happen when there are many CheckBoxes.
Is there any issue or solution related to this?

This might be related to this issue, which is supposed to be fixed.
TLTR: This seems to be an issue only for CheckBoxes and there seems to be no workaround for the moment. So, think again if this is what you really need.
I tried a few things and this is what I found (at least in my laptop):
CheckBoxes:
The max number you can instantiate in the MainWindow. (Haven't tried inPages.):
WinAppSDK v1.1: 286 items
WinAppSDK v1.2: 563 items
You get the exception even if you separate the CheckBoxes in different Grids. (Haven't tried different Pages.)
Buttons, ToggleButtons, even Expanders:
You can instantiate more than 10,000 items without getting the exception.

Related

Xamarin - How to display current position in CarouselView control?

Please help with CarouselView.
Xaml:
<carousel:CarouselViewControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Source="{Binding ImSource}" Aspect="AspectFill" Grid.Row="0" Grid.RowSpan="3" HeightRequest="220"/>
<Button
Grid.Row="0"
Text="1/1"
CornerRadius ="40"
FontSize="10"
HorizontalOptions="End"
BackgroundColor="Black"
TextColor="White"
WidthRequest="40"
HeightRequest="20"
Margin="0, 10, 10, 0"
Opacity="0.7"
Padding="0"/>
<controls:CircleImage
Grid.Row="2"
Source="users.png"
HorizontalOptions="Start"
WidthRequest="22"
Opacity="0.7"
Margin="10, 0, 0, 10"/>
</Grid>
</DataTemplate>
</carousel:CarouselViewControl.ItemTemplate>
</carousel:CarouselViewControl>
On my Button I need to display current position in Carousel.
But if in list one image - need to hide this button.
Button text must be like - 2(position)/3(list.Count)
I used: https://github.com/alexrainman/CarouselView
Please tell me - how I can do this.
Try to bind carousel position property to your ViewModel and then bind text from ViewModel to your button. So, something like this for CarouselViewControl:
<carousel:CarouselViewControl x:Name="CarouselView"
Position="{Binding CarouselPosition}"
ItemsSource="{Binding CarouselViewItems}">
...
</carousel:CarouselViewControl>
Your Button:
<Button
Grid.Row="0"
Text="{Binding CarouselPositionDisplayCounter}" .../>
In your ViewModel, add properties like it follows.
Carousel's current position:
private int _carouselPosition;
public int CarouselPosition
{
get { return _carouselPosition; }
set
{
_carouselPosition = value;
OnPropertyChanged();
}
}
Text binded to button:
public string CarouselPositionDisplayCounter =>
$"{(CarouselPosition + 1).ToString()}/{CarouselViewItems.Count.ToString()}";
And command when swiped:
public ICommand CarouselSwipedCommand => new Command(() =>
{
OnPropertyChanged(nameof(CarouselPositionDisplayCounter));
});
The carouselView already comes with it's own implementation of what you want:
You just need to add the ShowIndicators property to your xaml declaration:
<controls:CarouselViewControl ShowIndicators="True" ... />
Also there are properties for specifying shape and color of the indicators:
IndicatorsTintColor: page dot indicators fill color (default #C0C0C0).
CurrentPageIndicatorTintColor: selected page dot indicator fill color (default #808080).
IndicatorsShape: Indicators shape (default Circle).

TwoWay Data Binding with MVVM Light on Windows Phone 8.1

I'm trying to create a custom Button with ListPickerFlyout using MVVM. The result that i wanna reach is something like that:
custom Button with ListPickerFlyout
My problem is how to bind the SelectedItem from ListPickerFlyout to the content TextBlock.
I'm using MVVM Light Windows Phone 8.1 (Store Appp).
My Xaml code:
<Button Background="White"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="40" />
</Grid.ColumnDefinitions>
<!-- Content TextBlock -->
<TextBlock Text="{Binding MyVM.SelectedItem, Mode=TwoWay}"
Style="{StaticResource DefaultTextBlock}"
FontSize="22"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="10, 0, 0, 0"/>
<Image Height="20" Grid.Column="1"
VerticalAlignment="Center" HorizontalAlignment="Center"
Source="../Assets/icons/arrow_down.png"/>
</Grid>
<Button.Flyout>
<ListPickerFlyout PickerFlyoutBase.Title="$Items$"
ItemsSource="{Binding MyVM.listItems}"
SelectedItem="{Binding MyVM.SelectedItem, Mode=TwoWay}" >
<ListPickerFlyout.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding}"
Style="{StaticResource DefaultTextBlock}"
FontSize="22"/>
</StackPanel>
</DataTemplate>
</ListPickerFlyout.ItemTemplate>
</ListPickerFlyout>
</Button.Flyout>
And in MyVM i have
public string SelectedItem { get; set; }
Edit:
Solved the problem, i forgot to add RaisePropertyChanged("SelectedItem");.
So, in my MVVM class:
private string _selectedItem;
public string SelectedItem
{
get { return _selectedItem; }
set
{
if (_selectedItem != value)
{
_selectedItem = value;
RaisePropertyChanged("SelectedItem");
}
}
}
Just need to add the RaisePropertyChanged("SelectedItem"); in MVVM class.
The complete code:
private string _selectedItem;
public string SelectedItem
{
get { return _selectedItem; }
set
{
if (_selectedItem != value)
{
_selectedItem = value;
RaisePropertyChanged("SelectedItem");
}
}
}

Capture Element not using room from parent control

I am trying to create a page with a capture element and a button overlaid on top to take the picture.
The problem I've got is, the capture element won't use up the whole screen. There are bars above and below.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<CaptureElement
Grid.Row="0"
x:Name="capPreview"
Stretch="Uniform"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Tapped="capPreview_Tapped"
/>
<Button Content="Submit"
HorizontalAlignment="Center"
Grid.Row="1"
x:Name="btnTakePicture"
Click="btnTakePicture_Click">
<Button.Background>
<SolidColorBrush Color="Black" Opacity="100"/>
</Button.Background>
<Button.BorderBrush>
<SolidColorBrush Color="White"/>
</Button.BorderBrush>
</Button>
</Grid>
Edit: I have since used the code behind to rotate the capture element, however; upon doing so, the element now just has a box all around it instead of top and bottom.
<CaptureElement
Grid.Row="0"
x:Name="capPreview"
Tapped="capPreview_Tapped"
/>
Short of hard coding the height and width values, I am out of ideas.
It deos use the whole screen, the issue is the orientation of the preview is different than the orientation of the screen.
MediaCapture has a method SetPreviewRotation to handle this issue.
It works for me :) Just grid and Strech, If you want to have focus just make transparent grid outside CaptureElement
<Grid>
<Grid Tapped="SetFocus">
<CaptureElement x:Name="CaptureElement" Stretch="UniformToFill"/>
</Grid>
<Grid VerticalAlignment="Bottom">
<Button x:Name="SaveButton" Foreground="Transparent" IsDoubleTapEnabled="False" Width="48" Height="48" Background="Transparent" BorderBrush="Transparent"
Click="OnSaveButtonClicked" HorizontalAlignment="Stretch" Margin="12,0">
</Button>
</Grid>
</Grid>
Try this one it will capture directly with the button click
private async void Button_Click_3(object sender, RoutedEventArgs e)
{
Uri u = new Uri("ms-data:///local");
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("Photo.jpg");
IRandomAccessStream st = await file.OpenAsync(FileAccessMode.Read);
BitmapImage image = new BitmapImage();
image.SetSource(st);
img.Source = image;
}
<CaptureElement Name="element" Height="600"/>
<StackPanel>
<Button Content="Capture Image" Click="Button_Click_3"/>
</StackPanel>
<Image Name="img" Margin="0,0,0,0"/>

HubSection Header tap event?

How to get Tap event on Hub section Header?
<HubSection.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="" Foreground="#009CDE" Width="250"/>
<Image x:Name="SendToSap" Source="image/Sync_To_SAP.png" Width="40" Height="40" Margin="5,0,50,0" Tapped="SendToSap_Tapped"></Image>
</StackPanel>
</DataTemplate>
</HubSection.HeaderTemplate>
private void SendToSap_Tapped(object sender, TappedRoutedEventArgs e)
{
}
How to get this on image tap event?
Is it not working as is? Maybe you need to set IsTapEnabled="True"
If you need to add more code behind in your DataTemplate - usually you can move all the contents of the template into a UserControl and handle the events there.

Color Binding Not Working for Data Templates in Win8 App

I'm currently trying to add some sort of a Color Theme feature to a Win8 App I'm working at... I've though of making a binding from a vm, and everything works fine for static UI elements. But, I'm adding some notes (my model) into a DB, and they also appear on the screen into a GridView.
But in the declared DataTemplate for the GridView ItemTemplate, the Color Binding will not work at all...
My template looks like this :
<Grid Grid.Row="3" HorizontalAlignment="Left" Width="200" Height="200">
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="60"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="Lavender" Opacity="50"/>
<ScrollViewer Grid.Row="0">
<TextBlock Grid.Row="0" Text="{Binding Content}" Foreground="DodgerBlue" />
</ScrollViewer>
<Border Grid.Row="1" Background="DodgerBlue" Opacity="70"/>
<ScrollViewer Grid.Row="1">
<TextBlock Grid.Row="1" Text="{Binding Subject}" Foreground="LightBlue" />
</ScrollViewer>
<Border Grid.Row="2" Background="DodgerBlue" Opacity="70"/>
<TextBlock Grid.Row="2" Text="{Binding Importance}" Foreground="Black" FontSize="{StaticResource ComboBoxArrowThemeFontSize}" />
</Grid>
What I tried was simply instead of Foreground="DodgerBlue" to Foreground="{Binding ColorTheme}" but it had no effect, the SolidColorBrush was not acquired from vm....
Is there any workaround for this?
Many thanks in advance.
Altough I didn't really find out the actual explanation on why the below works (and I hope someone more experience, maybe could explain me), this post, seemed to have worked for me.
Not very sure, but was a matter of DataContext, so instead of trying a binding like this : Foreground={Binding ColorTheme}, I changed to this : Foreground={Binding DataContext.ColorTheme, ElementName=MyGridViewName}".
Color binding (or better: brush binding) should work just fine - in GridView.ItemTemplate scenario and elsewhere.
You haven't given enough info to pinpoint why it doesn't work in your case, but here is a small sample I've just tried out:
GridView to put in your page:
<GridView Width="600" Height="200" ItemsSource="{Binding GridItems}"
x:Name="GridViewName">
<GridView.ItemTemplate>
<DataTemplate>
<TextBlock Width="50" Height="50"
Foreground="{Binding Color}" Text="{Binding Text}" />
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
View model class bound as DataContext for your page:
public class ViewModel
{
public ViewModel()
{
GridItems = new List<GridItem>
{
new GridItem {Text = "First", Color = new SolidColorBrush(Colors.White)},
new GridItem {Text = "Second", Color = new SolidColorBrush(Colors.Yellow)},
new GridItem {Text = "Third", Color = new SolidColorBrush(Colors.Green)},
new GridItem {Text = "Fourth", Color = new SolidColorBrush(Colors.Red)},
};
}
}
GridItem class:
public class GridItem
{
public string Text { get; set; }
public Brush Color { get; set; }
}
The result:
EDIT:
I need to point out that inside data template DataContext is set to the current item of the bound collection (GridItems in my case) not to the page DataContext (ViewModel in my case).
This means that by setting {Binding Color} to a control property you're binding to GridItem.Color not to ViewModel.Color. To make the latter work you first need to access the parent DataContext using the ElementName syntax as you already suggested in your own answer: {Binding DataContext.ColorTheme, ElementName=GridViewName} - this binds to a named element on the page and allows you to access its properties, DataContext being ViewModel in this case.