Recently I have installed Xamarin.CommunityToolkit (Version: 1.3.1) for implementing the BadgeView. Also updated the Xamarin.Forms (Version: 5.0.0.2291) to the latest version. After that, I am facing some weird issues on my project. After the login the app is not opening the home page, scroll view is not working, collectionview scroll is not working, even some icon taps are also not firing.
All these features are working fine before installing Xamarin.CommunityToolkit. I have only installed CommunityToolkit and XF latest version. Are there any other packages or initialization required for the proper working of CommunityToolkit?
Other Nuget Packages in the Project
<PackageReference Include="Acr.UserDialogs" Version="7.1.0.446" />
<PackageReference Include="DLToolkit.Forms.Controls.FlowListView" Version="2.0.11" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.16" />
<PackageReference Include="Microsoft.Bcl" Version="1.1.10" />
<PackageReference Include="Microsoft.Bcl.Build" Version="1.0.21" />
<PackageReference Include="Microsoft.Net.Http" Version="2.2.29" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="PCLStorage" Version="1.0.2" />
<PackageReference Include="Plugin.MediaManager" Version="1.0.9" />
<PackageReference Include="Plugin.MediaManager.Forms" Version="0.8.11" />
<PackageReference Include="Rg.Plugins.Popup" Version="1.1.5.180" />
<PackageReference Include="SkiaSharp" Version="1.68.1-rc.147" />
<PackageReference Include="sqlite-net-pcl" Version="1.6.292" />
<PackageReference Include="Syncfusion.Xamarin.SfListView" Version="17.3.0.30" />
<PackageReference Include="Xam.Plugin.Connectivity" Version="3.2.0" />
<PackageReference Include="Xam.Plugin.HtmlLabel" Version="2.1.0" />
<PackageReference Include="Xam.Plugin.LatestVersion" Version="1.1.2" />
<PackageReference Include="Xam.Plugin.Media" Version="4.0.1.5" />
<PackageReference Include="Xam.Plugin.SimpleAudioPlayer" Version="1.3.1" />
<PackageReference Include="Xam.Plugins.Forms.ImageCircle" Version="3.0.0.5" />
<PackageReference Include="Xamarin.Essentials" Version="1.5.3.2" />
<PackageReference Include="Xamarin.FFImageLoading" Version="2.4.11.982" />
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.4.11.982" />
<PackageReference Include="Xamarin.FFImageLoading.Svg" Version="2.4.11.982" />
<PackageReference Include="Xamarin.FFImageLoading.Svg.Forms" Version="2.4.11.982" />
<PackageReference Include="Xamarin.FFImageLoading.Transformations" Version="2.4.11.982" />
<PackageReference Include="Xamarin.Forms" Version="4.8.0.1269" />
<PackageReference Include="XamForms.Enhanced.Calendar" Version="1.2.2" />
<PackageReference Include="Xamarin.Plugin.FilePicker" Version="2.1.34" />
Which package has compatibility issue with Xamarin.CommunityToolkit?
Update
I found that the issue is happening when I set the text value for badgeview from xaml.cs file after an API call. When I comment that part there is no issue. My issues are entire page scrollview is not working, collectionview is not working, text on badgeview is not working also app is very slow.
Sample project: https://drive.google.com/file/d/1B2bGcCxqJWmoU5tLLbNwUaW04mjAJm4S/view?usp=sharing
There is a function GetUserMedals() in HomePage1, I am setting badgeview text on that function. For reproducing this issue I need to add some private APIs into the demo. Please don't post it anywhere.
Got a perfect solution from my Microsoft thread.
Write a new badgeview.
Firstly, create CircleView.cs
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace MyProject
{
public partial class CircleView : BoxView
{
public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(nameof(CornerRadius), typeof(double), typeof(CircleView), 0.0);
public double CornerRadius
{
get { return (double)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
public CircleView()
{
// InitializeComponent();
}
}
}
Then create contentview called BadgeView.xaml and edit it to the Grid.
<?xml version="1.0" encoding="UTF-8"?>
<Grid xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local1="clr-namespace:MyProject"
x:Class="MyProject.BadgeView"
HeightRequest="30"
WidthRequest="30">
<local1:CircleView x:Name="BadgeCircle" HeightRequest="30" WidthRequest="30" CornerRadius="30" VerticalOptions="Center" HorizontalOptions="Center" />
<Label x:Name="BadgeLabel" TextColor="White" VerticalOptions="Center" HorizontalOptions="Center" VerticalTextAlignment="Center" HorizontalTextAlignment="Center" FontSize="15"/>
</Grid>
Here is BadgeView.xaml.cs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace MyProject
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class BadgeView : Grid
{
public static BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(BadgeView), "0", propertyChanged: (bindable, oldVal, newVal) =>
{
var view = (BadgeView)bindable;
view.BadgeLabel.Text = (string)newVal;
});
public static BindableProperty BadgeColorProperty = BindableProperty.Create("BadgeColor", typeof(Color), typeof(BadgeView), Color.Blue, propertyChanged: (bindable, oldVal, newVal) =>
{
var view = (BadgeView)bindable;
view.BadgeCircle.BackgroundColor = (Color)newVal;
});
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
public Color BadgeColor
{
get
{
return (Color)GetValue(BadgeColorProperty);
}
set
{
SetValue(BadgeColorProperty, value);
}
}
public BadgeView()
{
InitializeComponent();
BadgeLabel.Text = Text;
BadgeCircle.BackgroundColor = BadgeColor;
}
}
}
Then you need to create a custom renderer for this CircleView in android.
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using MyProject;
using MyProject.Droid;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(CircleView), typeof(CircleViewRenderer))]
namespace MyProject.Droid
{
public class CircleViewRenderer : BoxRenderer
{
private float _cornerRadius;
private RectF _bounds;
private Path _path;
public CircleViewRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
{
base.OnElementChanged(e);
if (Element == null)
{
return;
}
var element = (CircleView)Element;
_cornerRadius = TypedValue.ApplyDimension(ComplexUnitType.Dip, (float)element.CornerRadius, Context.Resources.DisplayMetrics);
}
protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
{
base.OnSizeChanged(w, h, oldw, oldh);
if (w != oldw && h != oldh)
{
_bounds = new RectF(0, 0, w, h);
}
_path = new Path();
_path.Reset();
_path.AddRoundRect(_bounds, _cornerRadius, _cornerRadius, Path.Direction.Cw);
_path.Close();
}
public override void Draw(Canvas canvas)
{
canvas.Save();
canvas.ClipPath(_path);
base.Draw(canvas);
canvas.Restore();
}
}
}
For iOS renderer.
[assembly: ExportRenderer(typeof(CircleView), typeof(CircleViewRenderer))]
namespace MyProject.iOS
{
public class CircleViewRenderer : BoxRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
{
base.OnElementChanged(e);
if (Element == null)
return;
Layer.MasksToBounds = true;
Layer.CornerRadius = (float)((CircleView)Element).CornerRadius / 2.0f;
}
}
}
In the end, we can use it in your HomePage1.cs Find the tag copy following code
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="33*" />
<ColumnDefinition Width="34*" />
<ColumnDefinition Width="33*" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Column="0">
<Grid>
<Grid TranslationY="-15">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image
Grid.Row="0"
Source="ic_white_dot_xx.png">
<Image.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>120</OnIdiom.Phone>
<OnIdiom.Tablet>240</OnIdiom.Tablet>
<OnIdiom.Desktop>120</OnIdiom.Desktop>
</OnIdiom>
</Image.HeightRequest>
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>120</OnIdiom.Phone>
<OnIdiom.Tablet>240</OnIdiom.Tablet>
<OnIdiom.Desktop>120</OnIdiom.Desktop>
</OnIdiom>
</Image.WidthRequest>
</Image>
<Image
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
Source="ic_medal_xx.png" >
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>60</OnIdiom.Phone>
<OnIdiom.Tablet>90</OnIdiom.Tablet>
<OnIdiom.Desktop>60</OnIdiom.Desktop>
</OnIdiom>
</Image.WidthRequest>
<Image.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>60</OnIdiom.Phone>
<OnIdiom.Tablet>90</OnIdiom.Tablet>
<OnIdiom.Desktop>60</OnIdiom.Desktop>
</OnIdiom>
</Image.HeightRequest>
</Image>
</Grid>
<views:BadgeView x:Name="medals_badge" Text="30" BadgeColor="Red" VerticalOptions="Start" HorizontalOptions="End"/>
</Grid>
</StackLayout>
<StackLayout Grid.Column="1">
<Grid>
<Grid TranslationY="-15">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image
Grid.Row="0"
Source="ic_white_dot_xx.png">
<Image.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>120</OnIdiom.Phone>
<OnIdiom.Tablet>240</OnIdiom.Tablet>
<OnIdiom.Desktop>120</OnIdiom.Desktop>
</OnIdiom>
</Image.HeightRequest>
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>120</OnIdiom.Phone>
<OnIdiom.Tablet>240</OnIdiom.Tablet>
<OnIdiom.Desktop>120</OnIdiom.Desktop>
</OnIdiom>
</Image.WidthRequest>
</Image>
<Image
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
Source="ic_badge_xx.png" >
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>60</OnIdiom.Phone>
<OnIdiom.Tablet>90</OnIdiom.Tablet>
<OnIdiom.Desktop>60</OnIdiom.Desktop>
</OnIdiom>
</Image.WidthRequest>
<Image.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>60</OnIdiom.Phone>
<OnIdiom.Tablet>90</OnIdiom.Tablet>
<OnIdiom.Desktop>60</OnIdiom.Desktop>
</OnIdiom>
</Image.HeightRequest>
</Image>
</Grid>
<views:BadgeView x:Name="badges_badge" Text="30" BadgeColor="Red" VerticalOptions="Start" HorizontalOptions="End"/>
</Grid>
</StackLayout>
<StackLayout Grid.Column="2">
<Grid>
<Grid TranslationY="-15">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image
Grid.Row="0"
Source="ic_white_dot_xx.png">
<Image.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>120</OnIdiom.Phone>
<OnIdiom.Tablet>240</OnIdiom.Tablet>
<OnIdiom.Desktop>120</OnIdiom.Desktop>
</OnIdiom>
</Image.HeightRequest>
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>120</OnIdiom.Phone>
<OnIdiom.Tablet>240</OnIdiom.Tablet>
<OnIdiom.Desktop>120</OnIdiom.Desktop>
</OnIdiom>
</Image.WidthRequest>
</Image>
<Image
HorizontalOptions="Center"
VerticalOptions="Center"
Source="ic_star_xx.png" >
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>60</OnIdiom.Phone>
<OnIdiom.Tablet>90</OnIdiom.Tablet>
<OnIdiom.Desktop>60</OnIdiom.Desktop>
</OnIdiom>
</Image.WidthRequest>
<Image.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>60</OnIdiom.Phone>
<OnIdiom.Tablet>90</OnIdiom.Tablet>
<OnIdiom.Desktop>60</OnIdiom.Desktop>
</OnIdiom>
</Image.HeightRequest>
</Image>
</Grid>
<views:BadgeView x:Name="star_badge" Text="30" BadgeColor="Red" VerticalOptions="Start" HorizontalOptions="End"/>
</Grid>
</StackLayout>
</Grid>
In the end, open your layout background code, you can find the GetUserMedals method. Set it directly.
medals_badge.Text = urlDetails.medals;
badges_badge.Text = urlDetails.badges;
star_badge.Text = urlDetails.stars;
Related
I've got a label that I want to bind to a boolean property (HasNotifications). However, when the property is false, the label stays visible. If I set the IsVisible property to false in the XAML, the label isn't visible so the issue appears to be with the binding.
XAML:
<AbsoluteLayout
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0,0,1,1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Text="Title"
HorizontalOptions="Center"
VerticalOptions="Center"
TextColor="White"
FontSize="Large"
FontAttributes="Bold"
Margin="5"
BindingContext="{x:Reference DashboardPageView}"
Grid.Row="0" />
<Label
Text="Notifications"
HorizontalOptions="Start"
VerticalOptions="Center"
TextColor="White"
FontSize="Medium"
FontAttributes="Bold"
Margin="3"
BindingContext="{x:Reference DashboardPageView}"
IsVisible="{Binding HasNotifications}"
Grid.Row="1" />
</Grid>
</AbsoluteLayout>
My viewmodel:
public bool HasNotifications
{
get => this.hasNotifications;
set => this.SetProperty(ref this.hasNotifications, value);
}
I don't think you have set the correct BindingContext. The HasNotifications is a property of your ViewModel while the BindingContext you set to your label is DashboardPageView.
I wrote a simple demo and hope you can get some idea from it:
In xaml:
<Grid
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0,0,1,1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Text="Title"
HorizontalOptions="Center"
VerticalOptions="Center"
TextColor="Black"
FontSize="Large"
FontAttributes="Bold"
Margin="5"
Grid.Row="0" />
<Label
Text="Notifications"
HorizontalOptions="Start"
VerticalOptions="Center"
TextColor="Black"
FontSize="Medium"
FontAttributes="Bold"
Margin="3"
IsVisible="{Binding HasNotifications}"
Grid.Row="1" />
<Button Text="change HasNotifications" Clicked="Button_Clicked" Grid.Row="2"/>
</Grid>
In cs:
public partial class MainPage : ContentPage
{
ViewModel myViewModel;
public MainPage()
{
InitializeComponent();
myViewModel = new ViewModel();
BindingContext = myViewModel;
}
private void Button_Clicked(object sender, EventArgs e)
{
myViewModel.HasNotifications = !myViewModel.HasNotifications;
}
}
public class ViewModel : INotifyPropertyChanged
{
bool _HasNotifications;
public event PropertyChangedEventHandler PropertyChanged;
public ViewModel()
{
}
public bool HasNotifications
{
set
{
if (_HasNotifications != value)
{
_HasNotifications = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("HasNotifications"));
}
}
}
get
{
return _HasNotifications;
}
}
}
Feel free to ask me any question if you have.
I am using a custom DialogService, the problem I have is that I first show a page as a modal and when sending to display the DialogPage it is apparently not shown but it really is behind the model page.
Invocation of the modal page
await _navigationService.NavigateAsync("ProfilePage", useModalNavigation: true);
Xaml CustomDialog
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="http://prismlibrary.com"
prism:DialogLayout.LayoutBounds="0.5, 0.5, -1, -1"
prism:DialogLayout.RelativeWidthRequest="0.60"
BackgroundColor="White"
x:Class="ComedorIndustrial.Prism.Views.MessageDialog">
<Grid Padding="30,60">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Source="iconoError.png" />
<Label Text="{Binding Title}" HorizontalTextAlignment="Center" TextColor="#ee3837" Grid.Row="1" Style="{StaticResource RobotoBold}" FontSize="30"/>
<Label Text="{Binding Message}" HorizontalTextAlignment="Center" TextColor="#bdbcc2" Grid.Row="2" FontSize="14" />
<Button Text="Volver a intentar"
Command="{Binding CloseCommand}"
BackgroundColor="#ee3837" BorderRadius ="25" TextColor="White" HorizontalOptions="FillAndExpand" Opacity="1" FontSize="12" Margin="0,15,0,0"
Grid.Row="3"/>
</Grid>
</ContentView>
Custom dialog invocation
public static void ShowAlert(this IDialogService dialogService, string title, string message)
{
var parameters = new DialogParameters
{
{ "title", title },
{ "message", message }
};
dialogService.ShowDialog("MessageDialog", parameters);
}
EDIT:
I have solved it!
Add the plugin: Prism.Plugin.Popups
And then add the following line of code in App.xaml.cs: containerRegistry.RegisterPopupDialogService();
The documentation is on the following page:
popups.prismplugins.com
Regards!
What you've described is a known bug in Prism 7.2. This issue is fixed in Prism 8, or as you've noted you can simply use the Prism.Plugin.Popups to use the PopupPage variant of the service.
Git: https://github.com/jimmyt1988/Test
I'm running on desktop windows 10 pc on UWP Local device "emulator"
I have a deep integer property in my view model that gets incremented by a button command.
When i do, the number disapears from the screen, and then if i resize my application, it will render correctly again.
What's happening?
It seems to work on the Android emulator.
Code
public DelegateCommand<FoodGroupModel> SubtractFromAmountEatenCommand { get; private set; }
...
SubtractFromAmountEatenCommand = new DelegateCommand<FoodGroupModel>((foodGroup) => SubtractFromAmountEaten(foodGroup));
...
public void SubtractFromAmountEaten(FoodGroupModel foodGroup)
{
if(foodGroup.AmountEaten != 0)
{
foodGroup.AmountEaten--;
}
}
...
public class FoodGroupModel : BindableBase
{
private int _amountEaten;
public int AmountEaten
{
get { return _amountEaten; }
set { SetProperty(ref _amountEaten, value); }
}
}
XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="...Views.MealPage">
<StackLayout>
<Label Text="{Binding Meal.Number}"/>
<ListView x:Name="FoodGroupsListView" ItemsSource="{Binding Meal.FoodGroups}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" TextColor="#bababa" Text="Group"></Label>
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Title}" />
<Label Grid.Row="0" Grid.Column="2" TextColor="#bababa" Text="Qty"></Label>
<Label Grid.Row="0" Grid.Column="3" Text="{Binding AmountEaten}" />
<Button Grid.Row="0" Grid.Column="4"
Command="{Binding Source={x:Reference FoodGroupsListView}, Path=BindingContext.UndoAmountEatenByOneCommand}"
CommandParameter="{Binding}"
Text="✖"></Button>
<Button Grid.Row="0" Grid.Column="5"
Command="{Binding Source={x:Reference FoodGroupsListView}, Path=BindingContext.SubtractFromAmountEatenCommand}"
CommandParameter="{Binding}"
Text="✔"></Button>
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
When i do, the number disapears from the screen, and then if i resize my application, it will render correctly again.
You might run into an issue: The changed notification of property binding won't work well(May be related to rerender) inside Xamarin ListView, Please report it in here: Bugzilla
In Windows runtime platform(Win/WP 8.1 & UWP), we have to use a workaround to temporarily avoid this:
private void RefreashFoodGroupModel()
{
if (Device.OS == TargetPlatform.Windows || Device.OS == TargetPlatform.WinPhone)
{
//var index = Meal.FoodGroups.IndexOf(foodGroup);
//Meal.FoodGroups.RemoveAt(index);
//Meal.FoodGroups.Insert(index, foodGroup);
var t = Meal.FoodGroups;
Meal.FoodGroups = new System.Collections.ObjectModel.ObservableCollection<FoodGroupModel>();
foreach (var item in t)
{
Meal.FoodGroups.Add(item);
}
}
}
Call the above method to refresh data after data change:
public void SubtractFromAmountEaten(FoodGroupModel foodGroup)
{
if(foodGroup.AmountEaten != 0)
{
foodGroup.AmountEaten--;
RefreashFoodGroupModel();
}
}
public void UndoAmountEatenByOne(FoodGroupModel foodGroup)
{
if (foodGroup.AmountEaten != foodGroup.Quantity)
{
foodGroup.AmountEaten++;
RefreashFoodGroupModel();
}
}
This workaround will cause the refresh of ListView items.
How to achieve a google material design entry / input in Xamarin.Forms (so no renderers, etc), even without the animation of the bottom label ?
Below code is a Xamarin.Forms google material design like entry approach. Total xaml + a little coding :)
Step1: Create a class in PCL project
public class CustomEntry : Entry
{
}
Step2: Create a control template in App.xaml
<ControlTemplate x:Key="MyControlTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<controls:CustomEntry x:Name="myEntry" Text="{TemplateBinding Text, Mode=TwoWay}" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="Start" IsPassword="{TemplateBinding IsPassword}" MinimumHeightRequest="25"/>
<BoxView Grid.Row="1" BackgroundColor="#D2D2D2" HeightRequest="1" HorizontalOptions="FillAndExpand" VerticalOptions="Start">
<BoxView.Triggers>
<DataTrigger TargetType="BoxView" Binding="{Binding Source={x:Reference myEntry}, Path=IsFocused}" Value="true">
<Setter Property="BackgroundColor" Value="Black" />
<Setter Property="HeightRequest" Value="2"/>
</DataTrigger>
</BoxView.Triggers>
</BoxView>
</Grid>
</ControlTemplate>
Step 3: Create a super material design entry class
public class MyMaterialDesignEntry : ContentView, INotifyPropertyChanged
{
public static readonly BindableProperty TextProperty =
BindableProperty.Create("Text", typeof(string), typeof(ContentPage), "");
public static readonly BindableProperty IsPasswordProperty =
BindableProperty.Create("IsPassword", typeof(bool), typeof(ContentPage), false);
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, (string)value); }
}
public bool IsPassword => (bool)GetValue(IsPasswordProperty);
public MyMaterialDesignEntry()
{
ControlTemplate = (ControlTemplate)Application.Current.Resources.FirstOrDefault(x => x.Key == "MyControlTemplate").Value;
}
}
Step 4: Use your super material design entry in xaml
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand">
<Label Text="Login"/>
<controls:MyMaterialDesignEntry Text="{Binding Login, Mode=TwoWay}"/>
</StackLayout>
Don't forget to add appropriate namespaces to your page xaml. It will tell you anyway.
I am just doing simple example in Silverlight, which retrieves data from database, can also insert, update and delete
I use child window for insert command, when I click "OK" Button at this ChildWindow it insert's in database but not renders on page(Silverlight content), there is same records therefore in database really inserts information. only after again re-lunch this page, it shows correctly(retrieves all data from server)
I'll post my source
this is Customers.xaml file
<UserControl x:Class="Store.Customers"
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"
xmlns:mv="clr-namespace:Store.ViewModel"
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="1000">
<UserControl.Resources>
<mv:ViewModel x:Key="ViewModel"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="127*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="130*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="91*" />
<RowDefinition Height="99*" />
<RowDefinition Height="110*" />
</Grid.RowDefinitions>
<Button Name="btnEdit" Content="Edit" HorizontalAlignment="Right" Grid.Column="1" Width="55" Height="30" Margin="0,225,0,0" Click="btnEdit_Click" />
<data:DataGrid Name="dgCustomer"
AutoGenerateColumns="False" VerticalScrollBarVisibility="Visible"
ItemsSource="{Binding PagedView, Mode=TwoWay, Source={StaticResource ViewModel}}"
Grid.Row="1" Grid.Column="1">
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="ID" Binding="{Binding CustomerID}"/>
<data:DataGridTextColumn Header="CompanyName" Binding="{Binding CompanyName}"/>
<data:DataGridTextColumn Header="ContactName" Binding="{Binding ContactName}"/>
<data:DataGridTextColumn Header="ContactTitle" Binding="{Binding ContactTitle}"/>
<data:DataGridTextColumn Header="Address" Binding="{Binding Address}"/>
<data:DataGridTextColumn Header="City" Binding="{Binding City}"/>
<data:DataGridTextColumn Header="Region" Binding="{Binding Region}"/>
<data:DataGridTextColumn Header="PostalCode" Binding="{Binding PostalCode}"/>
<data:DataGridTextColumn Header="Country" Binding="{Binding Country}"/>
<data:DataGridTextColumn Header="Phone" Binding="{Binding Phone}"/>
<data:DataGridTextColumn Header="Fax" Binding="{Binding Fax}"/>
<data:DataGridCheckBoxColumn Header="IsCitizen" Binding="{Binding IsCitizen}"/>
</data:DataGrid.Columns>
</data:DataGrid>
<data:DataPager HorizontalContentAlignment="Center" x:Name="myPager"
Source="{Binding ItemsSource, ElementName=dgCustomer}"
AutoEllipsis="True"
PageSize="10" Grid.Row="2" Grid.Column="1" VerticalAlignment="Top"/>
</Grid>
and this codebehinde
public partial class Customers : UserControl
{
public Customers()
{
InitializeComponent();
}
private void btnEdit_Click(object sender, RoutedEventArgs e)
{
new AddNewCustomer().Show();
}
}
this is childwindow
<controls:ChildWindow x:Class="Store.AddNewCustomer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:mv="clr-namespace:Store.ViewModel"
Width="450" Height="350"
Title="AddNewCustomer" >
<controls:ChildWindow.Resources>
<mv:ViewModel x:Key="ViewModel"/>
</controls:ChildWindow.Resources>
<Grid x:Name="LayoutRoot" Margin="2">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid>
<Grid.RowDefinitions >
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="30*"></ColumnDefinition>
<ColumnDefinition Width="70*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Customer ID :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtCustomerID"
Text="{Binding CustomerID, Mode=TwoWay, Source={StaticResource ViewModel}}" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="Company Name :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtCompanyName"
Text="{Binding CompanyName, Mode=TwoWay, Source={StaticResource ViewModel}}"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Contact Name :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="3" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtContactName" />
<TextBlock Grid.Row="4" Grid.Column="0" Text="Contact Title :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="4" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtContactTitle" />
<TextBlock Grid.Row="5" Grid.Column="0" Text="Address :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="5" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtAddressTitle" />
<TextBlock Grid.Row="6" Grid.Column="0" Text="City :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="6" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtCity" />
<TextBlock Grid.Row="7" Grid.Column="0" Text="Country :" VerticalAlignment="Center" Margin="2,0,0,0" />
<TextBox Grid.Row="7" Grid.Column="1" VerticalAlignment="Center" Margin="2,0" x:Name="txtCountry" />
</Grid>
<Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1" />
<Button x:Name="OKButton" Content="OK" Width="75" Height="23" HorizontalAlignment="Right" Click="OKButton_Click"
Margin="0,12,79,0" Grid.Row="1" Command="{ Binding AddNewCustomer, Mode=TwoWay, Source={StaticResource ViewModel} }"/>
</Grid>
this is My ViewModel
public class ViewModel : BaseViewModel
{
#region Fields
public ObservableCollection<Customer> _items;
public PagedCollectionView _view;
public string _customerID;
public string _companyName;
#endregion
#region Constructors
public ViewModel()
{
if (!this.IsDesignTime)
this.LoadCustomer();
}
#endregion
#region Properties
public ICommand AddNewCustomer { get { return new AddNewCustomerInfo(this); } }
public ObservableCollection<Customer> Items
{
get { return this._items; }
set
{
this._items = value;
this.OnPropertyChanged("Items");
}
}
public PagedCollectionView PagedView
{
get { return this._view; }
set
{
this._view = value;
this.OnPropertyChanged("PagedView");
}
}
public string CustomerID
{
get { return this._customerID;}
set
{
this._customerID = value;
this.OnPropertyChanged("CustomerID");
}
}
public string CompanyName
{
get { return this._companyName; }
set
{
this._companyName = value;
this.OnPropertyChanged("CompanyName");
}
}
#endregion
#region Methods
public void LoadCustomer()
{
DataServiceClient webService = new DataServiceClient();
webService.GetCustomersCompleted += new EventHandler<GetCustomersCompletedEventArgs>(webService_GetCustomersCompleted);
webService.GetCustomersAsync();
}
public void webService_GetCustomersCompleted(object sender, GetCustomersCompletedEventArgs e)
{
Items = e.Result;
PagedCollectionView pageView = new PagedCollectionView(Items);
pageView.PageSize = 10;
PagedView = pageView;
}
public void CreateCustomer()
{
DataServiceClient webservice = new DataServiceClient();
Customer cust = new Customer();
cust.CustomerID = this.CustomerID;
cust.CompanyName = this.CompanyName;
webservice.InsertCustomerCompleted += new EventHandler<InsertCustomerCompletedEventArgs>(webservice_InsertCustomerCompleted);
webservice.InsertCustomerAsync(cust);
LoadCustomer();
}
void webservice_InsertCustomerCompleted(object sender, InsertCustomerCompletedEventArgs e)
{
this.CreateResult = e.Result;
}
#endregion
}
public class AddNewCustomerInfo : ICommand
{
#region Fields
public ViewModel ViewModel { get; set; }
#endregion
#region Constructors
public AddNewCustomerInfo(ViewModel viewModel)
{
this.ViewModel = viewModel;
}
#endregion
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
this.ViewModel.CreateCustomer();
}
}
Grid and childwindow looks like this
As a simple basic solution, i would do this:
change your InsertCustomer web service call to return the updated Customer object that it just saved. This is so you will get an updated copy of the data object, complete with any keys/IDs. Doing this is a reasonably efficient way to do it, as you are making a call and accessing the database anyway, there is no point making two calls when it can be done in one.
once you've changed your webservice contract and regenerated your client proxy, the InsertCustomerCompletedEventArgs Result property should contain the updated Customer object. If you now add this data object to your PagedCollectionView it will automatically show up in your grid (as the PagedCollectionView implements INotifyCollectionChanged so the DataGrid binding will pick it up straight away, although be aware that paging may mean it isn't visible in the list you are currently looking at).