Xamarin Forms - Prism bound properties - Rendering issue - xamarin.forms

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.

Related

On using Detect Shake functionality in xamarin.forms UI is calling multiple times

I am working with xamarin.forms shake delect functionality, where on shaking the mobile I am calling a popup screen, but that screen is calling multiple times till I wont stop shaking the phone
RateUsPage.xaml
<?xml version="1.0" encoding="UTF-8"?>
<pages:PopupPage Title="Rate Us"
BackgroundColor="{DynamicResource TransparentPurple}"
Padding="0">
<pages:PopupPage.Animation>
<animations:ScaleAnimation PositionIn="Center" PositionOut="Center" ScaleIn="1.2" ScaleOut="0.8" DurationIn="400" DurationOut="300" EasingIn="SinOut" EasingOut="SinIn" HasBackgroundAnimation="True" />
</pages:PopupPage.Animation>
<StackLayout VerticalOptions="Center" HorizontalOptions="Center" Margin="20">
<StackLayout>
<Label Text="Rate Your Experience !!!" FontSize="{DynamicResource FontSize14}"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding Star1}" Grid.Row="0" Grid.Column="0">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding StarTappedCommand}" CommandParameter="1"/>
</Image.GestureRecognizers>
</Image>
<Image Source="{Binding Star2}" Grid.Row="0" Grid.Column="1">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding StarTappedCommand}" CommandParameter="2"/>
</Image.GestureRecognizers>
</Image>
<Image Source="{Binding Star3}" Grid.Row="0" Grid.Column="2">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding StarTappedCommand}" CommandParameter="3"/>
</Image.GestureRecognizers>
</Image>
<Image Source="{Binding Star4}" Grid.Row="0" Grid.Column="3">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding StarTappedCommand}" CommandParameter="4"/>
</Image.GestureRecognizers>
</Image>
<Image Source="{Binding Star5}" Grid.Row="0" Grid.Column="4">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding StarTappedCommand}" CommandParameter="5"/>
</Image.GestureRecognizers>
</Image>
</Grid>
</StackLayout>
<StackLayout>
<Grid Padding="10" RowSpacing="0" ColumnSpacing="15" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Button Padding="0" Grid.Row="0" Grid.Column="0" Command="{Binding CloseCommand}" FontSize="{DynamicResource FontSize14}" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Text="{Binding CancelText}"/>
</Grid>
</StackLayout>
</StackLayout>
</pages:PopupPage>
RateUsPageViewModel.cs
public class RateUsPageViewModel{
public RateUsPageViewModel(){
try
{
if (Accelerometer.IsMonitoring)
Accelerometer.Stop();
else
Accelerometer.Start(SensorSpeed.Game);
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Other error has occurred.
}
Accelerometer.ShakeDetected += Accelerometer_ShakeDetected;
}
private void Accelerometer_ShakeDetected(object sender, EventArgs e)
{
MainThread.BeginInvokeOnMainThread(() =>
{
_navigationService.ShowPopup<RatingUsPageViewModel>();
});
}
}
so when I use this code my UI is calling number of times
please help
thanks in advance
Remove your try and catch blocks and implement ToggleAccelerometer() method. call ToggleAccelerometer() method in your constructor and then again call in Accelerometer_ShakeDetected(object sender, EventArgs e). It should stop your problem.
public class RateUsPageViewModel
{
public RateUsPageViewModel()
{
ToggleAccelerometer();
Accelerometer.ShakeDetected += Accelerometer_ShakeDetected;
}
private void Accelerometer_ShakeDetected(object sender, EventArgs e)
{
MainThread.BeginInvokeOnMainThread(() =>
{
ToggleAccelerometer();
_navigationService.ShowPopup<RatingUsPageViewModel>();
});
}
public void ToggleAccelerometer()
{
try
{
if (Accelerometer.IsMonitoring)
Accelerometer.Stop();
else
Accelerometer.Start(speed);
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Other error has occurred.
}
}
}

Binding IsVisible to a bool property in Xamarin Forms

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.

Xamarin Forms content page make background color transparent

I have a requirement where in I need to display a list in a modal popup page.I am able to display a list but I cant make the background color transparent or semi transparent so that the page under it is partially visible.
I am pushing the page from my View Model using the folowing:
NavigationParameters oNavParams = new NavigationParameters();
oNavParams.Add("Mode", "FeedBack");
oNavParams.Add("selectedItem", txtFeedback);
_navigationService.NavigateAsync("PopupBox", oNavParams);
Here is my xaml code:
<?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"
xmlns:local="clr-namespace:MyApp"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="MyApp.Views.PopupBox">
<ContentPage.Content>
<AbsoluteLayout Padding="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<ContentView x:Name="popupListView" BackgroundColor="Transparent" Padding="10, 0" IsVisible="false" AbsoluteLayout.LayoutBounds="0, 0, 1, 1" AbsoluteLayout.LayoutFlags="All">
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<StackLayout Orientation="Vertical" HeightRequest="200" WidthRequest="300" BackgroundColor="White">
<ListView x:Name="sampleList">
</ListView>
</StackLayout>
</StackLayout>
</ContentView>
</AbsoluteLayout>
</ContentPage.Content>
</ContentPage>
Here is my code behind:
public PopupBox()
{
try
{
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false);
sampleList.ItemsSource = new List<string>
{
"Test ListView",
"Test ListView",
"Test ListView",
"Test ListView",
"Test ListView",
"Test ListView",
"Test ListView",
"Test ListView",
"Test ListView",
"Test ListView",
"Test ListView"
};
popupListView.IsVisible = true;
}
catch (Exception ex)
{
}
}
Here is the output:
I have also tried setting the following:
this.BackgroundColor= new Color(0, 0, 0, 0.4);
But it does not work.Is there any way I can achieve this?Using custom renderers or any other workaround to display a modal.
I don't wan't to use the Rg.Plugins.Popup as I had issues with it.So I was looking for an alternative.Please help.
This will not work without custom renderers.
A common way of obtaining the desired today is simply using Popup Page Plugin for Xamarin Forms (https://github.com/rotorgames/Rg.Plugins.Popup) nuget Rg.Plugins.Popup available.
As per #nicks comment please make changes into your code I will add few sample line of code that may help you.Rg.Plugins.Popup use this plugin and remove ContentPage add this one.
<?xml version="1.0" encoding="utf-8" ?>
<pages:PopupPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
xmlns:animations="clr-namespace:Rg.Plugins.Popup.Animations;assembly=Rg.Plugins.Popup">
<ListView x:Name="lst" BackgroundColor="Gray" HasUnevenRows="True" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid HorizontalOptions="FillAndExpand" Padding="10" BackgroundColor="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding DisplayName}" HorizontalOptions="StartAndExpand" Grid.Row="0" Grid.Column="0" FontAttributes="Bold"/>
<Label Text="{Binding DisplayContact}" HorizontalOptions="EndAndExpand" Grid.Row="0" Grid.Column="1" FontSize="11"/>
<Label Text="{Binding DisplayAddress}" VerticalOptions="StartAndExpand" Grid.Row="1" Grid.Column="0" FontSize="11"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</pages:PopupPage>
.cs file
using Rg.Plugins.Popup.Extensions;
using Rg.Plugins.Popup.Pages;
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class className : PopupPage
{
}
So after last invoking above class as a popup from a button click etc. so below is code
using Rg.Plugins.Popup.Extensions;
{
ClassName _className = new ClassName();
void Button1Click(object sender, System.EventArgs e)
{
Navigation.PushPopupAsync(_className);
}
}
Hope this will help you!!!!
As previously mentioned, you can use Rg.Plugins.Popup, and then just set the background as transparent as in the image (so that it is not just opaque).
Example of my popup page:
And on click:
Device.BeginInvokeOnMainThread(async () =>
{
Task<yourPopUpPage> task = Task.Run(() =>
{
return new yourPopUpPage();
});
task.Wait();
if (task.Status == TaskStatus.RanToCompletion)
{
Device.BeginInvokeOnMainThread(async () =>
{
await App.GetCurrentPage().Navigation.PushPopupAsync(task.Result);
});
};
});
If you update to Xamarin Forms 4.6 you can set:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
...
BackgroundColor="Transparent"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Page.ModalPresentationStyle="OverFullScreen">
<StackLayout HorizontalOptions="FillAndExpand"
</StackLayout>
</ContentPage>
and it works.
Pull Request: https://github.com/xamarin/Xamarin.Forms/pull/8551

How to implement a UWP Custom Renderer in Xamarin-Forms using FFImageLoading

I cant find a good example about use of FFImageLoading in a UWP custom renderer for xamarin forms, good example sites use to focus in android and ios only. My main issue is how to use this Image Class in the UWP resource, CachedImage should be used in PCL project if i understand correctly. So how i should continue here? The advance use of ImageService does not detail this. I probably dont understand something. thanks in advance.
This is my View Cell in PCL:
<ViewCell>
<Grid RowSpacing="0" Padding="5,1,10,1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="30"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="32"></RowDefinition>
<RowDefinition Height="32"></RowDefinition>
</Grid.RowDefinitions>
<ffimageloading:CachedImage Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Source="{Binding MyViewModel.Image}" Aspect="AspectFit" VerticalOptions="Center" LoadingPlaceholder = "resource://MyProject.Resources.loading.png" />
<Label Grid.Column="1" Grid.Row="0" Text="{Binding MyViewModel.Name}" FontSize="16" TextColor="Red" FontAttributes="Bold" VerticalOptions="End"></Label>
<Label Grid.Column="1" Grid.Row="1" Text="{Binding MyViewModel.Serie}" FontSize="11" TextColor="Gray" FontAttributes="Italic" VerticalOptions="Start"></Label>
<ffimageloading:CachedImage x:Name="check" Grid.Column="2" Grid.Row="0" Grid.RowSpan="2" Source="{Binding MyViewModel.Own, Converter={StaticResource BoolToOwnImageSourceConverter}}}" Aspect="AspectFit" VerticalOptions="Center">
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnCheckTapped"
Command="{Binding ChangeOwnCommand}"
CommandParameter="{Binding .}"/>
</Image.GestureRecognizers>
</ffimageloading:CachedImage>
</Grid>
<ViewCell.ContextActions>
<MenuItem Clicked="OnOwned" CommandParameter="{Binding .}" Text="Got it!" />
<MenuItem Clicked="OnNotOwned" CommandParameter="{Binding .}" Text="Not Yet" IsDestructive="True" />
</ViewCell.ContextActions>
Image source come from a image url stored in my view model
My main issue is how to use this Image Class in the UWP resource
If you want to custom image renderer. You could expand an attribute for xamarin image.
public class CustomImage : Image
{
public static readonly BindableProperty UriProperty = BindableProperty.Create(
propertyName: "Uri",
returnType: typeof(string),
declaringType: typeof(CustomImage),
defaultValue: default(string));
public string Uri
{
get { return (string)GetValue(UriProperty); }
set { SetValue(UriProperty, value); }
}
}
And you could invoke LoadUrl to set image for native control in the custom image render.
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
var customImage = (CustomImage)Element;
if (Control == null)
{
SetNativeControl(new Windows.UI.Xaml.Controls.Image());
}
if (e.OldElement != null)
{
}
if (e.NewElement != null)
{
if (!string.IsNullOrEmpty(customImage.Uri))
{
ImageService.Instance.LoadUrl(customImage.Uri).FadeAnimation(true).Into(Control);
}
else
{
// do some stuff
}
}
}

how rebind silverlight datagrid

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).

Resources